背水一战 Windows 10 (116) - 后台任务: 前台程序激活后台任务
背水一战 Windows 10 (116) - 后台任务: 前台程序激活后台任务
作者:webabcd
介绍
背水一战 Windows 10 之 后台任务
- 前台程序激活后台任务
示例
演示后台任务的应用(前台程序激活后台任务)
/BackgroundTaskLib/BackgroundTaskFore.cs
/* * 后台任务,用于演示如何在前台程序通过 api 激活后台任务 */ using System; using System.Threading.Tasks; using Windows.ApplicationModel.Background; using Windows.Storage; namespace BackgroundTaskLib { // 实现 IBackgroundTask 接口,其只有一个方法,即 Run() public sealed class BackgroundTaskFore : IBackgroundTask { public async void Run(IBackgroundTaskInstance taskInstance) { // 后台任务在执行中被终止执行时所触发的事件 taskInstance.Canceled += taskInstance_Canceled; // 异步操作 BackgroundTaskDeferral deferral = taskInstance.GetDeferral(); try { // 指定后台任务的进度 taskInstance.Progress = 0; // taskInstance.InstanceId - 后台任务实例的唯一标识,由系统生成,与前台的 IBackgroundTaskRegistration.TaskId 一致 StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(@"webabcdBackgroundTask\fore.txt", CreationCollisionOption.ReplaceExisting); for (uint progress = 10; progress <= 100; progress += 10) { await Task.Delay(1000); // 更新后台任务的进度(会通知给前台) taskInstance.Progress = progress; // 写入相关数据到指定的文件 await FileIO.AppendTextAsync(file, "progress: " + progress.ToString() + ", currentTime: " + DateTime.Now.ToString() + Environment.NewLine); } } finally { // 完成异步操作 deferral.Complete(); } } void taskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) { /* * BackgroundTaskCancellationReason - 后台任务在执行中被终止执行的原因 * Abort - 前台 app 调用了 IBackgroundTaskRegistration.Unregister(true) * Terminating - 因为系统策略,而被终止 * LoggingOff - 因为用户注销系统而被取消 * ServicingUpdate - 因为 app 更新而被取消 * ... - 还有好多,参见文档吧 */ } } }
BackgroundTask/Fore.xaml
<Page x:Class="Windows10.BackgroundTask.Fore" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.BackgroundTask" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <TextBlock Name="lblMsg" Margin="5" /> <Button Name="btnRegister" Content="注册一个后台任务" Margin="5" Click="btnRegister_Click" /> <Button Name="btnUnregister" Content="注销指定的后台任务" Margin="5" Click="btnUnregister_Click" /> <Button Name="btnRequest" Content="激活后台任务" Margin="5" Click="btnRequest_Click" /> </StackPanel> </Grid> </Page>
BackgroundTask/Fore.xaml.cs
/* * 演示后台任务的应用(前台程序激活后台任务) * * 注: * 1、需要引用后台任务项目,相关代码参见 BackgroundTaskLib/BackgroundTaskFore.cs * 2、需要在 Package.appxmanifest 添加“后台任务”声明,支持的任务类型选择“常规”,并指定 EntryPoint(后台任务的类全名),类似如下: * <Extension Category="windows.backgroundTasks" EntryPoint="BackgroundTaskLib.BackgroundTaskFore"> * <BackgroundTasks> * <Task Type="general" /> * </BackgroundTasks> * </Extension> */ using System; using System.Collections.Generic; using Windows.ApplicationModel; using Windows.ApplicationModel.Background; using Windows.Storage; using Windows.UI.Core; using Windows.UI.Popups; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; namespace Windows10.BackgroundTask { public sealed partial class Fore : Page { // 所注册的后台任务的名称 private string _taskName = "Fore"; // 所注册的后台任务的 EntryPoint,即后台任务的类全名 private string _taskEntryPoint = "BackgroundTaskLib.BackgroundTaskFore"; // 后台任务是否已在系统中注册 private bool _taskRegistered = false; // 后台任务执行状况的进度说明 private string _taskProgress = ""; // 实例化一个 ApplicationTrigger 类型的后台任务触发器(由前台程序通过 api 激活后台任务) private ApplicationTrigger applicationTrigger = new ApplicationTrigger(); public Fore() { this.InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { // 遍历所有已注册的后台任务(避免重复注册) foreach (KeyValuePair<Guid, IBackgroundTaskRegistration> task in BackgroundTaskRegistration.AllTasks) { if (task.Value.Name == _taskName) { // 如果找到了指定的后台任务,则为其增加 Progress 和 Completed 事件监听,以便前台 app 接收后台任务的进度汇报和完成汇报 AttachProgressAndCompletedHandlers(task.Value); _taskRegistered = true; break; } } UpdateUI(); } private async void btnRegister_Click(object sender, RoutedEventArgs e) { // 在注册后台任务之前,需要调用 BackgroundExecutionManager.RequestAccessAsync(),如果是更新过的 app 则在之前还需要调用 BackgroundExecutionManager.RemoveAccess() string appVersion = $"{Package.Current.Id.Version.Major}.{Package.Current.Id.Version.Minor}.{Package.Current.Id.Version.Build}.{Package.Current.Id.Version.Revision}"; if ((string)ApplicationData.Current.LocalSettings.Values["AppVersion"] != appVersion) { // 对于更新的 app 来说先要调用这个方法 BackgroundExecutionManager.RemoveAccess(); // 注册后台任务之前先要调用这个方法,并获取 BackgroundAccessStatus 状态 BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync(); if (status == BackgroundAccessStatus.Unspecified || status == BackgroundAccessStatus.DeniedBySystemPolicy || status == BackgroundAccessStatus.DeniedByUser) { // 无权限注册后台任务 await new MessageDialog("没有权限注册后台任务").ShowAsync(); } else { // 有权限注册后台任务 ApplicationData.Current.LocalSettings.Values["AppVersion"] = appVersion; } } // 用于构造一个后台任务 BackgroundTaskBuilder builder = new BackgroundTaskBuilder(); builder.Name = _taskName; // 后台任务的名称 builder.TaskEntryPoint = _taskEntryPoint; // 后台任务入口点,即后台任务的类全名 builder.SetTrigger(applicationTrigger); // 指定后台任务的触发器类型为 ApplicationTrigger(由前台程序通过 api 激活后台任务) // 向系统注册此后台任务 BackgroundTaskRegistration task = builder.Register(); // 为此后台任务增加 Progress 和 Completed 事件监听,以便前台 app 接收后台任务的进度汇报和完成汇报 AttachProgressAndCompletedHandlers(task); _taskRegistered = true; UpdateUI(); } private void btnUnregister_Click(object sender, RoutedEventArgs e) { // 遍历所有已注册的后台任务 foreach (KeyValuePair<Guid, IBackgroundTaskRegistration> task in BackgroundTaskRegistration.AllTasks) { if (task.Value.Name == _taskName) { // 从系统中注销指定的后台任务。唯一一个参数代表如果当前后台任务正在运行中,是否需要将其取消 task.Value.Unregister(true); break; } } _taskRegistered = false; UpdateUI(); } private async void btnRequest_Click(object sender, RoutedEventArgs e) { // 激活后台任务 await applicationTrigger.RequestAsync(); } private void AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration task) { // 为任务增加 Progress 和 Completed 事件监听,以便前台 app 接收后台任务的进度汇报和完成汇报 task.Progress += new BackgroundTaskProgressEventHandler(OnProgress); task.Completed += new BackgroundTaskCompletedEventHandler(OnCompleted); } private void OnProgress(IBackgroundTaskRegistration task, BackgroundTaskProgressEventArgs args) { // 获取后台任务的执行进度 _taskProgress = args.Progress.ToString(); UpdateUI(); } private void OnCompleted(IBackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs args) { // 后台任务已经执行完成 _taskProgress = "完成"; // 如果此次后台任务的执行出现了错误,则调用 CheckResult() 后会抛出异常 try { args.CheckResult(); } catch (Exception ex) { _taskProgress = ex.ToString(); } UpdateUI(); } private async void UpdateUI() { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { btnRegister.IsEnabled = !_taskRegistered; btnUnregister.IsEnabled = _taskRegistered; if (_taskProgress != "") lblMsg.Text = "进度:" + _taskProgress; }); } } }
OK
[源码下载]