【问题标题】:Execution of code in the background when the event is triggered触发事件时在后台执行代码
【发布时间】:2017-04-25 16:43:12
【问题描述】:

我目前正在完成活动本身的所有工作,但这似乎不是首选方式,因为在几分钟不活动后代码不会在手机上执行。事件声明如下:

public PlaybackModel()
{
    ...
    queue.CurrentItemChanged += async (o, ea) =>
    {
        var res = ScrobbleHelper.TrySend(ea.OldItem);
        await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
        {
            var bg = App.Ref.IsBackground;
            currentItem = o.CurrentItem;
        });
    };
    ...
}

此事件似乎有 5 种可能的结果:

  1. 当应用在前台时,scrobble 可以正常工作;
  2. 当应用在后台运行且屏幕打开(用户正在执行其他操作)时,scrobble 可以正常工作;
  3. 最近关闭屏幕时(当关闭屏幕后不久发送请求时),scrobble 工作正常
  4. scrobble 无法发送,因此它会在屏幕关闭超过一分钟时被缓存(似乎互联网连接被切断,因此 scrobble 被缓存在本地);
  5. 如果屏幕长时间关闭,代码根本不会执行。

考虑到这一点,我正在考虑使用带有ApplicationTrigger 的进程内后台任务来调用scrobbler,但我不确定我该怎么做。

一方面,这是唯一可以在没有应用程序在前台运行的情况下执行代码的事情,但另一方面,如果代码本身没有被事件处理程序调用,我不确定任务是否会被触发。

UWP 的任何其他 API 或功能可以在这种情况下提供帮助吗?如果没有,我该如何执行后台任务以达到最大效率?

谢谢!

【问题讨论】:

  • 首先触发事件的是什么?想知道是否有任何背景触发器适用于您的场景。这样,您的应用程序可以正常挂起,并且系统会在触发器触发时唤醒您的代码。 docs.microsoft.com/en-us/uwp/api/…
  • 此事件由this Microsoft API 触发。我正在使用 MediaPlayer 类来播放音乐。我如何调用这些背景触发器,从哪里以及如何将所有内容联系在一起?

标签: c# .net background event-handling uwp


【解决方案1】:

在 Windows 设备上,在前台应用程序中运行后台事件有一些限制,即当屏幕关闭一段时间后它们会被冻结。这是为了减少电池消耗,整个过程在内存中暂停,不触发任何事件。

确实有一种方法可以在专用进程上运行后台任务,即使设备有一段时间未使用,该进程也能正常运行。您需要创建一个实现IBackgroundTask 的专用类,然后将其固定到适当的触发器并注册它。 (如果应用程序必须将内容写入应用程序状态,您还需要考虑一些 IPC 接口,因为后台任务作为不同的进程运行。)

【讨论】:

  • 那么 In-Process 任务不是一个好的解决方案吗?如果没有在后台调用事件,我将如何实施,更重要的是,触发进程外后台任务?
【解决方案2】:

听起来您的应用正在播放媒体,并且您希望防止它在应用进入后台或屏幕锁定时暂停。最好的方法是使用去年通过周年更新 (1607) 发布的新的进程内后台媒体播放功能。这是文档:

https://docs.microsoft.com/en-us/windows/uwp/audio-video-camera/background-audio

需要注意的一点是,操作系统可能会在不使用网络适配器时使网络适配器进入睡眠状态。从您描述的症状来看,这可能就是您在这里遇到的问题。尝试将此代码添加到您的应用中,以确保即使屏幕被锁定,网络连接仍保持活跃:

Windows.Media.Playback.MediaPlayer mp;
public void CreatePlayer()
{
  Windows.Media.Core.MediaBinder mb = new Windows.Media.Core.MediaBinder();
  mb.Binding += Mb_Binding;           
  var ms = Windows.Media.Core.MediaSource.CreateFromMediaBinder(mb);
  mp = new Windows.Media.Playback.MediaPlayer();
  mp.CommandManager.IsEnabled = false;
  mp.Source = ms;
}

private void Mb_Binding(Windows.Media.Core.MediaBinder sender, Windows.Media.Core.MediaBindingEventArgs args)
{
  var d = args.GetDeferral();
}

谢谢, Stefan Wick - Windows 开发者平台

【讨论】:

  • 正在使用它。
  • 好的,可能我误解了问题描述。您的问题是应用程序被暂停还是网络连接断开?
  • 实际上两者兼而有之。虽然Background Media Playback 功能支持后台媒体播放,但它仍然不能让我完全控制它。媒体确实在后台播放,但任何应该响应MediaPlayerMediaPlaybackList 引发的事件的事件都不能很好地工作。尤其是在长时间不活动之后。您链接的文章确实提到了这一点,并说我需要使用 MaintananceTriggerTimerTrigger 的后台任务,但这在我的场景中不起作用,因为它需要被调用每当歌曲播放完不到 15 分钟
  • 所以基本上,你给我的东西我已经确定了,在这个问题中,我正在寻找更多关于如何实现任务的细节和信息,以便它的行为与我所拥有的相似在原始问题(事件)中尽可能。每次更改歌曲时,我都需要调用此任务 - 通过单击按钮或仅仅因为它完成播放。这就是为什么事件似乎是最好的解决方案,不幸的是它们不能在后台工作。我不确定我应该使用哪种类型的后台任务,也不知道什么是这种场景的最佳触发器。
  • 通过声明该功能,您的应用只要正在播放媒体就不会暂停,并且事件将继续正常触发。但是,如果功能取决于网络连接,您可能会遇到操作系统的省电功能,其中网络适配器在不使用时会进入睡眠状态。我将编辑答案以添加一种解决方法,以确保连接保持活动状态。
猜你喜欢
  • 2020-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多