与众不同 windows phone (12) - Background Task(后台任务)之 PeriodicTask(周期任务)和 ResourceIntensiveTask(资源密集型任务)
作者:webabcd
介绍
与众不同 windows phone 7.5 (sdk 7.1) 之后台任务
- PeriodicTask - 周期任务
- ResourceIntensiveTask - 资源密集型任务(通常用于手机与电脑同步数据)
示例
演示如何注册和运行 PeriodicTask 类型的任务和 ResourceIntensiveTask 类型的任务
1、后台代理
MyScheduledTaskAgent/ScheduledAgent.cs
/* * 本例演示如何由后台任务定时弹出 Toast,以及如何定时更新应用程序瓷砖的 Badge * 建议使用 ScheduledTaskAgent 类型的模板创建此项目 * * BackgroundAgent - 后台代理类,抽象类,它是 ScheduledTaskAgent、AudioPlayerAgent 和 AudioStreamingAgent 的基类 * NotifyComplete() - 用于通知系统,代理已经完成了当前的任务,调用此方法后,系统才会去准备执行下一次任务 * Abort() - 用于通知系统,放弃此次和以后的任务,对应的 ScheduledAction 的 IsScheduled 将变为 false * * ScheduledTaskAgent - 后台计划任务代理类,抽象类 * OnInvoke(ScheduledTask task) - 后台任务每次执行时都会调用此方法 * * ScheduledAgent - 用于演示后台任务的类,继承自 ScheduledTaskAgent,需要重写 ScheduledTaskAgent 的 OnInvoke() 方法 * * DeviceStatus.ApplicationMemoryUsageLimit - 程序在此时被分配到的内存数量(单位:字节),每次获取此值可能都不一样,但是肯定不会超过 6MB * * ShellToast - 用于管理 Toast * Title - Toast 的标题 * Content - Toast 的内容 * NavigationUri - 单击 Toast 之后链接到的目标地址(Uri 类型) * Show() - 显示 Toast(注:如果 Show 方法的调用程序正在前台运行,则不会显示 Toast) * * ScheduledActionService.LaunchForTest(string name, TimeSpan delay) * 对于 ScheduledTask 类型的任务,在指定的时间后马上执行任务。其用于开发目的,仅在开发工具部署的应用程序中有效 * PeriodicTask 和 ResourceIntensiveTask 均继承自 ScheduledTask */ using System.Windows; using Microsoft.Phone.Scheduler; using Microsoft.Phone.Shell; using Microsoft.Phone.Info; using System; using System.Linq; namespace MyScheduledTaskAgent { public class ScheduledAgent : ScheduledTaskAgent { /* * _classInitialized - 用于标记 ScheduledAgent 是否已经被初始化 * 标记成 volatile 是为了避免编译器认为此字段无外部修改,而将其优化放入寄存器(标记成 volatile 的字段只会放在内存中) * 一般来说,多任务环境下各任务间共享的字段应该被标记为 volatile */ private static volatile bool _classInitialized; public ScheduledAgent() { if (!_classInitialized) { _classInitialized = true; Deployment.Current.Dispatcher.BeginInvoke(delegate { Application.Current.UnhandledException += ScheduledAgent_UnhandledException; }); } } private void ScheduledAgent_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) { if (System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Break(); } } protected override void OnInvoke(ScheduledTask task) { string toastTitle = ""; if (task is PeriodicTask) toastTitle = "PeriodicTask"; else if (task is ResourceIntensiveTask) toastTitle = "ResourceIntensiveTask"; string toastContent = "MemoryUsageLimit: " + DeviceStatus.ApplicationMemoryUsageLimit; // 弹出 Toast ShellToast toast = new ShellToast(); toast.Title = toastTitle; toast.Content = toastContent; toast.NavigationUri = new Uri("/BackgroundTask/BackgroundAgentDemo.xaml?param=abc¶m2=xyz", UriKind.Relative); toast.Show(); // 更新应用程序磁贴的 Badge ShellTile applicationTile = ShellTile.ActiveTiles.First(); StandardTileData newTile = new StandardTileData { Count = new Random().Next(1, 99) }; applicationTile.Update(newTile); #if DEBUG // 15 秒后执行“task.Name”任务 ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(15)); #endif NotifyComplete(); } } } /* * 主程序引用此项目后,会在 manifest 中添加如下信息: * <ExtendedTask Name="BackgroundTask"> * <BackgroundServiceAgent Specifier="ScheduledTaskAgent" Name="MyScheduledTaskAgent" Source="MyScheduledTaskAgent" Type="MyScheduledTaskAgent.ScheduledAgent" /> * </ExtendedTask> */
2、前台注册指定的后台代理
BackgroundAgentDemo.xaml
<phone:PhoneApplicationPage x:Class="Demo.BackgroundTask.BackgroundAgentDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray.IsVisible="True"> <StackPanel Orientation="Vertical"> <Button Name="btnStartPeriodicTask" Content="Start Periodic Task Agent" Click="btnStartPeriodicTask_Click" /> <Button Name="btnStartResourceIntensiveTask" Content="Start Resource Intensive Task Agent" Click="btnStartResourceIntensiveTask_Click" /> <TextBlock x:Name="lblMsg" /> </StackPanel> </phone:PhoneApplicationPage>
BackgroundAgentDemo.xaml.cs
/* * 本例演示:如何注册 PeriodicTask 类型的任务和 ResourceIntensiveTask 类型的任务 * * ScheduledAction - 所有计划活动的基类,抽象类。ScheduledNotification 和 ScheduledTask 继承自此类 * Name - ScheduledAction 的名称,此名称即 ID * ScheduledTask - 计划任务类,抽象类。PeriodicTask 和 ResourceIntensiveTask 继承自此类 * Description - 针对后台任务的描述,将显示在 设置->应用程序-后台任务 中 * 支持及不支持的 api 参见:http://msdn.microsoft.com/en-us/library/hh202962(v=vs.92) * 内存使用的上限值为 6MB,具体上限值从 ApplicationMemoryUsageLimit 获取(根据实际情况每次获取到的值可能都不一样,但肯定不会超过 6MB) * 一个计划任务最多执行两周,两周后要重新 ScheduledAction.Add(),每次 ScheduledAction.Add() 之后最多执行两周 * 任务连续两次崩溃之后将会被取消 * * PeriodicTask - 周期任务 * PeriodicTask 每 30 分钟被执行一次,每次最多持续 25 秒 * ResourceIntensiveTask - 资源密集型任务(通常用于手机与电脑同步数据) * ResourceIntensiveTask 每次最多持续 10 分钟 * 需要使用外部电源,或使用本机电池时电量在 90% 以上 * 需要 WiFi 或 PC 连接网络 * 必须在锁屏状态下且无手机呼叫 * * ScheduledActionService - 管理 ScheduledAction 的类 * ScheduledActionService.GetActions<T>() where T : ScheduledAction - 查找系统中已注册的 ScheduledAction 类型的数据 * ScheduledAction.Find(string name) - 按名称查找指定的 ScheduledAction * ScheduledAction.Remove(string name) - 按名称删除指定的 ScheduledAction * ScheduledAction.Add(ScheduledAction action) - 注册一个新的 ScheduledAction * ScheduledAction.Replace(ScheduledAction action) - 更新指定的 ScheduledAction * ScheduledActionService.LaunchForTest(string name, TimeSpan delay) - 对于 ScheduledTask 类型的任务,在指定的时间后马上执行任务。其用于开发目的,仅在开发工具部署的应用程序中有效 */ using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.Phone.Controls; using Microsoft.Phone.Scheduler; namespace Demo.BackgroundTask { public partial class BackgroundAgentDemo : PhoneApplicationPage { private PeriodicTask _periodicTask; private string _periodicTaskName = "PeriodicTask"; private ResourceIntensiveTask _resourceIntensiveTask; private string _resourceIntensiveTaskName = "ResourceIntensiveTask"; public BackgroundAgentDemo() { InitializeComponent(); } protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { if (NavigationContext.QueryString.Count > 0) { lblMsg.Text = "参数 param 的值为:" + this.NavigationContext.QueryString["param"]; lblMsg.Text += Environment.NewLine; lblMsg.Text += "参数 param2 的值为:" + this.NavigationContext.QueryString["param2"]; } base.OnNavigatedTo(e); } private void btnStartPeriodicTask_Click(object sender, RoutedEventArgs e) { // 实例化一个新的 PeriodicTask _periodicTask = ScheduledActionService.Find(_periodicTaskName) as PeriodicTask; if (_periodicTask != null) ScheduledActionService.Remove(_periodicTaskName); _periodicTask = new PeriodicTask(_periodicTaskName); _periodicTask.Description = "用于演示 PeriodicTask"; try { // 每次都注册一个新的 PeriodicTask,以最大限度避免两周后无法执行的问题 ScheduledActionService.Add(_periodicTask); #if DEBUG // 1 秒后执行任务 ScheduledActionService.LaunchForTest(_periodicTaskName, TimeSpan.FromSeconds(1)); #endif } catch (InvalidOperationException exception) { if (exception.Message.Contains("BNS Error: The action is disabled")) { // 代理已被禁用 } if (exception.Message.Contains("BNS Error: The maximum number of ScheduledActions of this type have already been added.")) { // 代理的数量超过了设备的限制(设备的最大代理数是由设备进行硬性限制的,最低值是 6) } } catch (Exception ex) { } } private void btnStartResourceIntensiveTask_Click(object sender, RoutedEventArgs e) { // 实例化一个新的 ResourceIntensiveTask _resourceIntensiveTask = ScheduledActionService.Find(_resourceIntensiveTaskName) as ResourceIntensiveTask; if (_resourceIntensiveTask != null) ScheduledActionService.Remove(_resourceIntensiveTaskName); _resourceIntensiveTask = new ResourceIntensiveTask(_resourceIntensiveTaskName); _resourceIntensiveTask.Description = "用于演示 ResourceIntensiveTask"; try { // 每次都注册一个新的 ResourceIntensiveTask,以最大限度避免两周后无法执行的问题 ScheduledActionService.Add(_resourceIntensiveTask); #if DEBUG // 1 秒后执行任务 ScheduledActionService.LaunchForTest(_resourceIntensiveTaskName, TimeSpan.FromSeconds(1)); #endif } catch (InvalidOperationException exception) { if (exception.Message.Contains("BNS Error: The action is disabled")) { // 代理已被禁用 } if (exception.Message.Contains("BNS Error: The maximum number of ScheduledActions of this type have already been added.")) { // 代理的数量超过了设备的限制(设备的最大代理数是由设备进行硬性限制的,最低值是 6) } } catch (Exception ex) { } } } }
OK
[源码下载]