UWP Guidelines for background tasks

Support your app with background tasks

从Win10 1607开始,可以在后台支持媒体播放了,参考Play media in the background

幕后任务可以有两种实现方式,一种在其他进程中运行,一种在本进程中运行(1607新增)。 同进程的幕后任务实现简单,但是生命周期同本进程。异进程的幕后任务实现复杂,好处是可以与本进程的生命周期脱钩。

异进程的幕后任务需要实现IBackgroundTask 接口,并通过BackgroundTaskBuilder注册。

幕后任务(Background Task)可以看成一个被某些事件触发,然后短暂执行的轻量型任务。

SystemTrigger 类别的幕后任务,可以相应以下事件(SystemTriggerType

  • InternetAvailable The Internet becomes available.
  • NetworkStateChange A network change such as a change in cost or connectivity occurs.
  • OnlineIdConnectedStateChange Online ID associated with the account changes.
  • SmsReceived A new SMS message is received by an installed mobile broadband device.
  • TimeZoneChange The time zone changes on the device (for example, when the system adjusts the clock for daylight saving time).

即便,幕后任务可以添加一些额外条件(SystemConditionType,在触发事件发生时判断是否要执行。也就是说,幕后任务是否运行,可以由触发时机以及运行条件共同决定。

跨进程的幕后任务需要在应用程序声明文件(application manifest)中定义。进程内的幕后任务则不需要。

一些实时的事件触发器:

  • TimeTrigger
  • ControlChannelTrigger.
  • PushNotificationTrigger

在注册幕后任务之前,应用必须调用RequestAccessAsync。在App更新之后,最好在启动的时候使用RemoveAccess和RequestAccessAsync来刷新幕后任务的触发事件。

对于某些事件触发器,能够注册的幕后任务个数有限。比如对于ApplicationTrigger、MediaProcessingTrigger以及DeviceUseTrigger,只能被一个幕后任务注册。

更多系统触发器:

  • UserPresent The background task is triggered when the user becomes present.
  • UserAway The background task is triggered when the user becomes absent.
  • ControlChannelReset The background task is triggered when a control channel is reset.
  • SessionConnected The background task is triggered when the session is connected.
  • LockScreenApplicationAdded An app tile is added to the lock screen.
  • LockScreenApplicationRemoved An app tile is removed from the lock screen.

一般情况下,幕后任务只能执行30秒。在内存不足(Out-of-memory)发生时,系统会生成一个内存不足异常,不弱不处理这个异常,那么幕后任务会被系统扑灭。可以通过MemoryManager来查询应用的内存使用。在系统级别对幕后任务总个数有所限制,如果这个限制达成,那么RequestAccessAsync会失败。

Respond to system events with background tasks

对于应用商店(非企业以及自行发布的程序)中的程序,Battery Saver开启时可以阻止幕后任务运行。

对于实时任务,比如由ControlChannelTrigger 和PushNotificationTrigger ,它们被认为是关键的,所以执行的时候的CPU资源是有保障的。有一些不重要的任务比如Maintenance Trigger触发的,是插电才能用的。

有一些幕后任务只有在应用处于前台运行时才能触发,比如DeviceUseTrigger。有一些事件只能被有有权限(设备制造商允许)的App触发,比如DeviceServicingTrigger。碰巧的是,这两个事件都不能在进程内幕后任务中执行。

通过事件和本地存储,幕后任务可以汇报进度,完成或者取消情况,甚至是异常给App。应用启动的时候,最后检查 BackgroundTaskBuilder.AllTasks中的幕后任务是不是最新的。

Guidelines for background tasks

更多关于同进程幕后任务的限制:

  • 一些触发器不能使用:DeviceUseTrigger, DeviceServicingTrigger, IoTStartupTask
  • 同进程幕后任务不支持VoIP。

对于ApplicationTrigger、MediaProcessingTrigger以及DeviceUseTrigger这些只能注册单个幕后任务的触发器,如果任务数超过了,则会抛出异常。

大部分触发器只能允许幕后任务允许30秒,少部分允许允许10分钟。幕后任务设计时应该以减少资源消耗为准则。

如果幕后任务由异步调用,主要要使用BackgroundTaskDeferral,否则任务会在Run返回(或者同进程情况下OnBackgroundActivated 返回时)被终止。

异进程的幕后任务必须在app manifest中声明,否则无法注册。对于异进程幕后任务,你可以选择让它们在同一个进程,还是不同进程中允许。通过app manifest的Resource group指定。参考application schema referenceDeclare background tasks in the application manifest

应用更新的时候,可以使用系统触发器ServicingComplete 来更新幕后注册列表。以及做一些其他更新。

RequestAccessAsync会失败并返回BackgroundAccessStatus.DeniedByUser。如果用户在设置中禁用了幕后任务。

幕后任务(同进程和异进程)检查清单:

  • Associate your background task with the correct trigger.
  • Add conditions to help ensure your background task runs successfully.
  • Handle background task progress, completion, and cancellation.
  • Re-register your background tasks during app launch. This ensures that they are registered the first time the app is launched. It also provides a way to detect whether the user has disabled your app’s background execution capabilities (in the event registration fails).
  • Check for background task registration errors. If appropriate, attempt to register the background task again with different parameter values.
  • For all device families except desktop, if the device becomes low on memory, background tasks may be terminated. If an out of memory exception is not surfaced, or the app does not handle it, then the background task will be terminated without warning and without raising the OnCanceled event. This helps to ensure the user experience of the app in the foreground. Your background task should be designed to handle this scenario.

异进程幕后任务检查清单:

  • Create your background task in a Windows Runtime component.
  • Do not display UI other than toasts, tiles, and badge updates from the background task. In the Run method, request deferrals for each asynchronous method call, and close them when the method is done. Or, use one deferral with async/await.
  • Use persistent storage to share data between the background task and the app.
  • Declare each background task in the application manifest, along with the type of triggers it is used with. Make sure the entry point and trigger types are correct.
  • Do not specify an Executable element in the manifest unless you are using a trigger that should be run in the same context as the app (such as the ControlChannelTrigger).

同进程幕后任务检查清单:

  • When cancelling a task, ensure that the BackgroundActivated event handler exits before the cancellation occurs or the whole process will be terminated.
  • Write background tasks that are short-lived. Background tasks are limited to 30 seconds of wall-clock usage.
  • Do not rely on user interaction in background tasks.

Access sensors and devices from a background task

DeviceUseTrigger可以让你的幕后任务与外围设备打交道,比如同步数据或者监控传感器。为了保持电量,使用DeviceUseTrigger 时需要遵循一定的策略。这也是该文档的重点。

(本篇完)