引言:
当Windows Phone应用程序不在前台运行的时候,抑或者应用程序在休眠状态下或者设备锁住的时候,计划任务和后台代理则可以运行在后台,帮助应用程序来处理一些简单的事务,今天开始,我将梳理自己所掌握的Windows Phone知识并结合内部资料,争取更深的吃透Windows Phone平台的运行机制.以此勉之!(PS: 不会按任何顺序讲述,需要读者具备并了解XAML的数据绑定、MVVM设计模式以及其他相关的知识)。
后台代理介绍
1、后台代理的类型
- 周期性的任务,即:Periodic Task
- 资源密集性的任务,即: Resource Intensive Task.
2、当创建后台代理时,你需要了解..
- 一个应用程序仅能运行一个后台代理, 它可以是周期性的,也可以是资源密集性的,也可以是两者共存。
- 任务计划的运行,取决于你事先注册 了哪种类型的代理任务。
- 在后台代理中,不要把业务的关键逻辑写进去,否则,你将会像调进泥潭一样不能自拔,当初我们写云城客户端时就碰到了类似的错误。
3、应该考虑哪些计划任务的约束条件?
- 3.1、不支持的APIs
- 有些API在计划任务中是不被支持的.
- 3.2、内存使用的限制
- 只有11MB内存可供利用
- 音频类代理能够使用到15MB内存。
- 3.3、每两周可以改变计划任务的需求设定
- 如果想让某个计划任务不再运行,可以设置该任务的过期时间属性对象。
- 过期时间属性的值至少要2周。
- 如果后台代理任务被用于更新动态瓷贴,那么过期时间自动顺延2周时间。
- 如果需要在锁屏界面中显示通知,当你再次调用后台代理时,过期时间同样也会顺延2周时间.
- 假设你的应用有照片上传的功能,使用了资源密集型任务,这可能要求一直保持该任务运行,此时,你需要到 照片+相机 的设置页中开启.
- 3.4、如果应用程序有两次不定期的崩溃,那么,后台代理任务的执行会变得混乱,不按原来的计划执行。
以上是在使用后台代理时应用注意的一些事项,各位在开发过程中,一定要注意这些,尤其是内存及时间的要求,接下来,我们来详细看看周期性代理的实现原理及注意事项:
4、周期性代理
在我们正式开始编写周期性代理任务之前,先来了解下周期代理的一些约束条件及注意事项,以便我们能够更好的掌握、利用其特性。
- 4.1、计划任务执行的间隔:通常是30分钟执行一次。
- 4.2、计划任务的连续性:每25秒运行。
- 4.3、如果开启电源节约模式,周期性代理将不会运行。
- 4.4、在每台设备中,只允许运行6个周期性代理。
5、代码实战
- 使用VS2013 RC创建简单的后台代理项目,如图:
- 添加主要命名空间
using Microsoft.Phone.Shell;
- 在OnInvoke()方法中实现代理功能,本例子主要通过后台代理,将消息通知到前台,实现过程如下:
protected override void OnInvoke(ScheduledTask task) { //TODO: Add code to perform your task in background string ToastMessage = string.Empty; if (task is PeriodicTask) { ToastMessage = string.Format("周期性任务正在运行..."); } var toast = new ShellToast(); toast.Title = "后台代理实战!"; toast.Content = ToastMessage; toast.Show();
NotifyComplete(); #if DEBUG_AGENT //在调试模式下设定代理的运行时间间隔,如果不写这段代理,那就只能等待.... ScheduledActionService.LaunchForTest(task.Name,TimeSpan.FromSeconds(60)); #endif }
- 实现MainPage.xaml页面的UI布局.
- 在项目中创建:ViewModel文件夹,创建名称为:PeriodicTaskConfigure.cs的周期代理任务配置。
#define DEBUG_AGENT using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Phone.Scheduler; namespace PhoneApp1.ViewModel { public class PeriodicTaskConfigure : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string name) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(name)); } } PeriodicTask periodicTask { get; set; } public string Name = "周期性代理"; private bool? _isEnabled; public bool? IsEnabled { get { return _isEnabled; } set { _isEnabled = value; OnPropertyChanged("IsEnabled"); } } private bool? _isScheduled; public bool? IsScheduled { get { return _isScheduled; } set { _isScheduled = value; OnPropertyChanged("IsScheduled"); } } private DateTime? _lastScheduledTime; public DateTime? LastScheduledTime { get { return _lastScheduledTime; } set { _lastScheduledTime = value; OnPropertyChanged("LastScheduledTime"); } } private DateTime? _expirationTime; public DateTime? ExpirationTime { get { return _expirationTime; } set { _expirationTime = value; OnPropertyChanged("ExpirationTime"); } } private string _LastExitReason;
public string LastExitReason { get { return _LastExitReason; } set { _LastExitReason = value; OnPropertyChanged("LastExitReason"); } } public void Page_Active() { periodicTask = ScheduledActionService.Find(Name) as PeriodicTask; if (periodicTask != null) { } } public void StartPeriodicAgent() { periodicTask = ScheduledActionService.Find(Name) as PeriodicTask; if (periodicTask != null) { RemoveAgent(); } periodicTask = new PeriodicTask(Name); periodicTask.Description = "这里描述周期性代理的用途."; try { ScheduledActionService.Add(periodicTask); LoadPeriodicTaskData(); #if(DEBUG_AGENT) ScheduledActionService.LaunchForTest(Name, TimeSpan.FromSeconds(60)); #endif } catch (Exception e) { } } public void RemoveAgent() { try { ScheduledActionService.Remove(Name); EmptyPeriodicData(); } catch (Exception e) { } } private void LoadPeriodicTaskData() { this.IsEnabled = periodicTask.IsEnabled; this.IsScheduled = periodicTask.IsScheduled; this.LastScheduledTime = periodicTask.LastScheduledTime; this.LastExitReason = periodicTask.LastExitReason.ToString(); this.ExpirationTime = periodicTask.ExpirationTime; } private void EmptyPeriodicData() { this.IsEnabled = null; this.IsScheduled = null; this.LastScheduledTime = null; this.LastExitReason = null; ; this.ExpirationTime = null; } }
}
- 在App.xaml.cs中声明 PeriodicTaskConfigure属性,在App()构造函数中实现该类的一个对象。
private static PeriodicTaskConfigure _periodicTaskConfigure; public static PeriodicTaskConfigure periodicTaskConfigure { get { return _periodicTaskConfigure; } }
- 在MainPage.xaml.cs中,将DataContext设置为PeriodicTaskConfigure的实现。
public MainPage() { InitializeComponent(); this.DataContext = App.periodicTaskConfigure; // Sample code to localize the ApplicationBar //BuildLocalizedApplicationBar(); }
- 经过如上设置,我们就可以在MainPage.xaml中去调用PeriodicTaskConfigure对象中的实现方法。
private void PeriodicCheckBox_Checked(object sender, RoutedEventArgs e) { App.periodicTaskConfigure.StartPeriodicAgent(); } private void PeriodicCheckBox_Unchecked(object sender, RoutedEventArgs e) { App.periodicTaskConfigure.RemoveAgent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { App.periodicTaskConfigure.Page_Active(); }
最终的实现效果是这个样子地:
你的运行效果是这样的么?如果不是,别着急,这里有: Windows Phone 8 后台代理 (P1:周期性代理) 源码
如果有任何问题,请到 http://ask.metrofeng.com 提问,24小时在线解答。
转载于:https://blog.51cto.com/weishibo/1312713