UWP -- Background Task 深刻解析

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

1. 重点

锁屏问题

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

await BackgroundExecutionManager.RequestAccessAsync();

资源限制

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

在内存受限的设备上,对于能够安装在一台设备上并在任何给定时间使用后台任务的应用数量有所限制。 若是超出该数量,将没法调用注册全部后台任务时所需的 RequestAccessAsyncapp

若是后台任务尝试执行超过此限制的操做,则该操做将失败,并可能生成内存不足的异常状况,但该任务能够处理此状况若是该任务没法处理内存不足的异常状况,或者因为尝试的操做的性质致使没法生成内存不足的异常状况,任务将当即终止less

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

进程内后台任务 entry-point

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

节电模式

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

时间限制

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

大多数触发器限制为 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.

相关文章
相关标签/搜索