UWP -- Background Task 深入解析

原文:UWP -- Background Task 深入解析

1. 重点

锁屏问题

从 Windows 10 开始,用户无须再将你的应用添加到锁屏界面,即可利用后台任务,通用 Windows 应用必须在注册任何后台触发器类型之前调用 RequestAccessAsync:

await BackgroundExecutionManager.RequestAccessAsync();

资源限制

由于对于内存较低的设备的资源约束,后台任务可能具有内存限制,该限制决定了后台任务可以使用的内存上限

在内存受限的设备上,对于可以安装在一台设备上并在任何给定时间使用后台任务的应用数量有所限制。 如果超出该数量,将无法调用注册所有后台任务时所需的 RequestAccessAsync

如果后台任务尝试执行超过此限制的操作,则该操作将失败,并可能生成内存不足的异常情况,但该任务可以处理此情况如果该任务无法处理内存不足的异常情况,或者由于尝试的操作的性质导致无法生成内存不足的异常情况,任务将立即终止

你可以使用 MemoryManager PAI 查询当前内存使用量和限制,以发现上限(若有),并监视正在进行的后台任务内存使用量

进程内后台任务 entry-point

对于进程内后台活动,不要设置 TaskEntryPoint.。将其保留为空可启用默认入口点,这是 Application 对象上称为 OnBackgroundActivated() 的一种新的受保护方法

节电模式

除非你豁免你的应用,以便它可以在节电模式打开时仍可以运行后台任务和接收推送通知,否则当节电模式功能启用时,如果设备未连接到外部电源且电量低于指定剩余电量,它将阻止后台任务运行。 这不会阻止你注册后台任务

时间限制

后台任务受其基于触发器类型获取的时钟时间使用的限制。

大多数触发器限制为 30 秒的时钟时间使用,如果后台活动的运行时间超过执行时间限制,即使在应用的前台进程内运行,后台活动也会终止(进程内后台任务)。而另一些触发器在完成耗时任务时最多可以运行 10 分钟。 为了延长电池使用时间并为前台应用提供最佳用户体验,后台任务应该是轻量级任务

2. 概述

Reason: Windows Store apps have their threads suspended when not in the forground.
Benefit: This prevents background apps fom consuming battery power and prevents apps the user is not interacting with from affecting the responsiveness of the foreground app.

  • System can update your tile or show a toast notification even when your app is suspended or terminated. —- Toast and Notification
  • Your app could transfer large files even when in the background. — Networking

All using background task. Windows Store apps can execute code when not in the foreground by using background task.

Background Task architecture

  1. Implement the code you want executed as a background task.
  2. Decide what triggers your background task code (eg: timer , user log in , ..)
  3. Add a manifest declaration so that Windows knows how to active background task code.
    只是决定什么情况下触发,从而运行
  4. Register your app’s background tasks with Windows the first time your app is activated.

注意:
第一次需要在代码中注册
此外,需要在项目中添加对 WinRT 的引用,reference

Background task 启动过程

When a trigger occurs, Windows creates a new process, loads your background task code into it, and calls an entry point. The background task process runs in the package’s app container. (background task typically execute in a different process than the app’s process)

注:Windows Store apps runs in a different security context than a desktop apps. The security context is called app container, and it restricts which resources a Windows Store app can access.

a new process —- 独立进程 (backgroundtaskhost.exe)

需要说明,一般background task 运行在哪个进程,由manifest – declarations – background task – Executable 决定,文档上:

For most of the triggers, you must leave this blank, Which tells Windows to use its own BackgroundTaskHost.exe process.(系统的BackgroundTaskHost.exe, 任务管理器只看见一个)

Background is not allowed to update the app’s user interface, but can update tiles and badges, or cause the display of a toast notification

重点:

The background task process runs in the package’s app container. This means that the manifest’s package capabilities and app declarations do apply to the background task process. The background task process can write to the package’s data setting and folders. (for an app and its background tasks to communicate with each other). One process can signal when data is ready by calling ApplicationData’s SingalDataChanged method.

Your app must run at least once in order to register a background task and its desired trigger with Windows.(第一次在代码中注册)

Once registered, your app can be running, suspended, or even terminated. When the trigger occurs, Windows starts your app’s background task.

//在注册前运行即可
await Windows.ApplicationModel.Background.BackgroundExecutionManager.RequestAccessAsync();

Background task is the only way to execute code when a PC is in Connected Standby mode.

3. 使用后台任务支持应用

3.1 在后台播放媒体

3.2 进程内后台任务和进程外后台任务

有两种方法可以实现后台任务:

  • 进程内
    • 应用及其后台进程在同一进程中运行;
  • 进程外
    • 应用及其后台进程分别在单独的进程中运行。 进程内后台支持在 Windows 10 版本 1607 中引入,目的是简化编写后台任务。 但仍可以编写进程外后台任务

进程外后台任务实现为操作系统在独立进程 (backgroundtaskhost.exe) 中运行的轻型类。 进程外后台任务编写来实现 IBackgroundTask 接口的类。 通过使用 BackgroundTaskBuilder 类注册后台任务。 注册后台任务时,类名称将用于指定入口点

4. 后台任务指南

内外进程中的任务

CPU 配额

后台任务受其基于触发器类型获取的时钟时间使用的限制。 大多数触发器限制为 30 秒的时钟时间使用,而另一些触发器在完成耗时任务时最多可以运行 10 分钟。 为了延长电池使用时间并为前台应用提供最佳用户体验,后台任务应该是轻量级任务。

使用 BackgroundTaskDeferral

如果后台任务类运行异步代码,则确保使用延迟。 否则,当使用 Run 方法(或针对进程内后台任务使用 OnBackgroundActivated 方法)时,你的后台任务可能会提前终止

BackgroundTaskDeferral _deferral; // Note: defined at class scope so we can mark it complete inside the OnCancel() callback if we choose to support cancellation
    public async void Run(IBackgroundTaskInstance taskInstance)
    {
        _deferral = taskInstance.GetDeferral()
        //
        // TODO: Insert code to start one or more asynchronous methods using the
        //       await keyword, for example:
        //
        // await ExampleMethodAsync();
        //

        _deferral.Complete();
    }

准备应用更新

如果你的应用将更新,请创建和注册一个 ServicingComplete 后台任务,以便取消注册适用于前一版本应用的后台任务,并注册适用于新版本应用的后台任务。 此时也非常适合在前台运行的上下文之外执行所需的应用更新

建议每个 app 都可以装一个,它可以在 你没运行之前做一些操作

5. 1.Implement your Background Task’s code

 namespace MyApp.BackgroundTasks
    { // NOTE: determines filename "MyApp.BackgroundTasks.WinMD"
        using Windows.ApplicationModel.Background;  // For IBackgroundTask & IBackgroundTaskInstance
        using Windows.Storage;

        // NOTE: WinRT components MUST be public and sealed
        public sealed class MyBackgroundTask : IBackgroundTask
        {
            public void Run(IBackgroundTaskInstance taskInstance)
            {          // Register cancelation handler (see the "Background task cancellation" section)
                       // NOTE: Once canceled, a task has 5 seconds to complete or the process is killed
                taskInstance.Canceled +=              (IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) =>
                {
                    // TODO: Tell task it should cancel itself as soon as possible...
                };

                // Recommended: Adjust task behavior based on CPU and network availability
                // For example: A mail app could download mail for all folders when cost is
                // low and only download mail for the Inbox folder when cost is high
                switch (BackgroundWorkCost.CurrentBackgroundWorkCost)
                {
                    case BackgroundWorkCostValue.Low:       // The task can use CPU & network
                    case BackgroundWorkCostValue.Medium:    // The task can use some CPU & network
                    case BackgroundWorkCostValue.High:      // The task should avoid using CPU & network
                    // This example records the last trigger time in an application data setting
                    // so the app can read it later if it chooses. We do regardless of work cost.
                        ApplicationData.Current.LocalSettings.Values["LastTriggerTime"] =  DateTimeOffset.Now;
                        break;
                }
            }
        }
    }

Must implemented as a WinRT comment in VS. This project simply creates a dynamic-link library file. The file extension is .WinMD instead of .DLL .

When you register the full name of this class. The windows will be ready to execute this task ,it will try to load a .WinMD file whose name matches the namespace.

加载这文件时候,会先加载构造函数,不写系统默认一个空构造,你写了就不去加载这个空的构造函数。(包含run)

6. Decide what triggers your Background Task’s code

注册要运行的后台任务

通过在 BackgroundTaskRegistration.AllTasks 属性中迭代,查明后台任务是否已注册。 此步骤非常重要;如果应用不检查现有后台任务注册,则它可能会轻松多次注册该任务,这会导致性能问题和工作结束前超出任务的最大可用 CPU 时间

    var taskRegistered = false;
    var exampleTaskName = "ExampleBackgroundTask";

    foreach (var task in BackgroundTaskRegistration.AllTasks)
    {
        if (task.Value.Name == exampleTaskName)
        {
            taskRegistered = true;
            break;
        }
    }

如果后台任务尚未注册,则使用 BackgroundTaskBuilder 创建你的后台任务的一个实例。 任务入口点应为命名空间为前缀的后台任务的名称。

后台任务触发器控制后台任务何时运行。 有关可能的触发器的列表,请参阅 SystemTrigger。
例如,此代码创建一个新后台任务并将其设置为在 TimeZoneChanged 触发器引发时运行:

var builder = new BackgroundTaskBuilder();

builder.Name = exampleTaskName;
builder.TaskEntryPoint = "RuntimeComponent1.ExampleBackgroundTask";
builder.SetTrigger(new SystemTrigger(SystemTriggerType.TimeZoneChange, false));

(可选)在触发器事件发生后,你可以添加条件控制任务何时运行。 例如,如果你不希望在用户存在前运行任务,请使用条件 UserPresent。 有关可能条件的列表,请参阅 SystemConditionType

builder.AddCondition(new SystemCondition(SystemConditionType.UserPresent));

通过在 BackgroundTaskBuilder 对象上调用 Register 方法来注册后台任务。 存储 BackgroundTaskRegistration 结果,以便可以在下一步中使用该结果

BackgroundTaskRegistration task = builder.Register();

通用 Windows 应用必须在注册任何后台触发器类型之前调用 RequestAccessAsync:

await BackgroundExecutionManager.RequestAccessAsync();

使用事件处理程序处理后台任务完成

你应该使用 BackgroundTaskCompletedEventHandler 注册一个方法,以便应用可以从后台任务中获取结果。 当启动或恢复应用时,如果自从上次在应用前台运行后后台任务就已完成,将调用标记方法。 (如果应用当前位于前台时后台任务完成,将立即调用 OnCompleted 方法

private void OnCompleted(IBackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs args)
    {
        var settings = Windows.Storage.ApplicationData.Current.LocalSettings;
        var key = task.TaskId.ToString();
        var message = settings.Values[key].ToString();
        UpdateUI(message);
    }

回到已注册后台任务的位置。 在该代码行之后,添加一个新的 BackgroundTaskCompletedEventHandler 对象。 提供 OnCompleted 方法作为 BackgroundTaskCompletedEventHandler 构造函数的参数:

task.Completed += new BackgroundTaskCompletedEventHandler(OnCompleted);

在应用清单中声明你的应用使用后台任务

略^^

具体 Trigger 及其中区别

7. Add manifest declaration

The meaning of Executable field, this tells Windows which process to execute when the trigger fires. (!!!)

This process will load your WinRT component’s .WinMD file and execute your task’s code. There are two options for this field. For most of the triggers, you must leave this field blank, which tells Windows to use its own Background TaskHost.exe process. (Windows or App container?)

注释:Windows Store apps run in a different security context than desktop apps. This security context is called an app container (discussed in the appendix, “App containers”), and it restricts which resources a Windows Store app can access.

For a PushNotificationTrigger, you can leave this field blank or you can specify(指定) the name of your own app’s executable. If you use the latter, Windows will have your app’s process load the WinRT component and run the task in the same process as your app.

This is not the recommended thing to do, but it allows your background task’s code the ability to access the same state (memory) as your app. However, if your app is suspended, all threads but the thread running the background task code remain suspended, so you must not perform any interthread communication or deadlocks will occur. In addition, because the GUI thread remains suspended, the background task cannot update the app’s user interface. If the app’s process is not running, Windows will activate it, but the app is not launched with a main view or hosted view activation. The result of all this is that your background task cannot have any expectations of the app’s state and, in fact, the app might not have its state fully initialized.

For a ControlChannelTrigger, you must not leave the Executable field blank; instead, you must specify your app’s executable name and your WinRT component’s .WinMD file must load in the app’s process.

As mentioned previously, the ControlChannelTrigger is used for RTC apps, and these apps typically have a socket open in the background task. For the app to respond to the incoming call on the socket, the background task and the app have to share the same process. Everything I said earlier still holds true in this scenario too; that is, the app will not be fully initialized and you should avoid interthread communication.

For the declaration’s Entry Point field, enter the full name (including the namespace) of the WinRT class you created in step 1 (for example, MyApp.BackgroundTasks.MyBackgroundTask). This tells the host process the name of the .WinMD file to load (MyApp.BackgroundTasks.WinMD) and the name of the class to construct in order to call its Run method.

Lock-Screen allowing that app’s background tasks to consume system resources even when the PC is on battery power. These apps typically have a real-time networking requirement like a chat or VoIP application

最多显示七个,可以自己去系统里面设置(你的app得支持lock-screen 才行)

8.

时间: 2024-11-08 23:23:12

UWP -- Background Task 深入解析的相关文章

与众不同 windows phone (12) - Background Task(后台任务)之 PeriodicTask(周期任务)和 ResourceIntensiveTask(资源密集型任务)

原文:与众不同 windows phone (12) - Background Task(后台任务)之 PeriodicTask(周期任务)和 ResourceIntensiveTask(资源密集型任务) [索引页][源码下载] 与众不同 windows phone (12) - Background Task(后台任务)之 PeriodicTask(周期任务)和 ResourceIntensiveTask(资源密集型任务) 作者:webabcd 介绍与众不同 windows phone 7.5

与众不同 windows phone (13) - Background Task(后台任务)之后台文件传输(上传和下载)

原文:与众不同 windows phone (13) - Background Task(后台任务)之后台文件传输(上传和下载) [索引页][源码下载] 与众不同 windows phone (13) - Background Task(后台任务)之后台文件传输(上传和下载) 作者:webabcd 介绍与众不同 windows phone 7.5 (sdk 7.1) 之后台任务 后台文件传输(下载) 后台文件传输(上传) 示例1.演示如何实现后台文件传输(下载)BackgroundTransfe

与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder)

原文:与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder) [索引页][源码下载] 与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder) 作者:webabcd 介绍与众不同 windows phone 7.5 (sdk 7.1) 之后台任务 Alarm - 警报 Reminder - 提醒 示例1.演示 Alarm(按一个

[CSS基础教程]background属性详细解析

CSS背景图像属性background详细解析 CSS的背景属性"background"提供了众多属性值,如颜色.图像.定位等,为网页背景图像的定义提供了极大的便利.看看background提供的属性值: background : background-color  | background-image  | background-repeat  | background-attachment  | background-position 从属性值的名字就可以很明白的看出来,分别是:颜

在UWP应用中加入Cortana语音指令集

原文:在UWP应用中加入Cortana语音指令集     本文介绍小娜语音指令集的使用场景,如何将UWP应用接入小娜的语音指令集,使用户直接通过小娜启动应用并使用应用中 一些轻量级的功能.文中以必应词典作为实例讲解必应词典UWP版本是如何接入小娜语音功能的.     小娜算得上是Windows 10一大卖点,跟邻居家的Google Now和Siri比起来叫好声也更多.除了经典开始菜单的"回归",UWP通用应用架构,营销人员口中三句话不离的,自然还有微软小娜.其实微软小娜是具有第三方应用

android-使用 async task 如何返回对象?

问题描述 使用 async task 如何返回对象? 我想从 async task 里解析后返回 tweets 的列表,但是我从 task 中没有返回 arraylist.谁能提供一个解决方案啊? @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ArrayList listItems = new ArrayList(); new myAsyncTask(

android+json+php+mysql实现用户反馈功能方法解析_Android

相信每个项目都会有用户反馈建议等功能,这个实现的方法很多,下面是我实现的方法,供大家交流.首先看具体界面,三个字段.名字,邮箱为选填,可以为空,建议不能为空.如有需要可以给我留言.  下面贴出布局代码,这里用到一个<include layout="@layout/uphead">就是把另外一个布局文件引入到这个布局中. 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?> &l

android+json+php+mysql实现用户反馈功能方法解析

相信每个项目都会有用户反馈建议等功能,这个实现的方法很多,下面是我实现的方法,供大家交流.首先看具体界面,三个字段.名字,邮箱为选填,可以为空,建议不能为空.如有需要可以给我留言.   下面贴出布局代码,这里用到一个<include layout="@layout/uphead">就是把另外一个布局文件引入到这个布局中. 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?> &

我的Android进阶之旅------&amp;gt;Android Activity的singleTask加载模式和onActivityResult方法之间的冲突

         今天调试一个bug的时候,情景如下:           一个Activity A,需要用startActivityForResult方法开启Activity B.Activity B的launch mode被设置为singleTask,那么在Activity B开启之后的瞬间(未等B返回任何result),Activity A中的onActivityResult方法就会被调用,并且收到一个RESULT_CANCEL的request code.          然后在Acti