Windows 8 – 后台处理
本文解释了后台处理在 Windows 8 应用商店应用开发中的重要性,
后台进程用于各种应用程序,以在后台执行各种不需要用户交互的活动。主要基于 CPU 的长时间运行进程就是使用后台进程设计的。与其它领域相比,后台进程在 Windows 8 应用商店应用开发中起着重要作用。由于在应用商店应用中引入了新的进程生命周期,因此需要后台进程。
在本文中,我们将讨论 Windows 应用商店应用的进程生命周期以及后台进程在 Windows 8 中的重要性。在本文中,我们将研究一些示例场景,例如后台任务实现、后台音频播放和锁屏应用。
Windows 应用商店应用进程生命周期管理 (PLM)
在传统应用程序中,用户决定应用程序的生命周期,例如打开应用、切换到另一个应用以及终止应用程序。在 Windows 8 中,进程发生了变化,Windows 控制着应用程序的生命周期进程。不应通过对话框要求用户关闭或退出应用程序。即使应用程序崩溃,用户也不会收到任何指示。一次最多运行一到两个应用程序在前台,所有其他应用程序看起来都在后台运行。
这个前台应用程序拥有对 CPU、网络和内存资源的完全访问权限,系统可以完全专注于一个应用程序,资源完全分配给前台应用程序。这引入了新的进程生命周期。
图1:进程生命周期
最初,应用程序处于“未运行”状态。当用户调用应用程序时,它会开始激活应用程序并显示启动屏幕,然后显示应用程序。当用户将另一个应用程序切换到前台时,当前应用程序将移至挂起状态。如果用户再次将应用程序切换到前台,它将以先前的状态恢复应用程序。当用户关闭应用程序或系统因资源不足而终止应用程序时,应用程序将被终止。
应用程序状态更改与各种事件相关联,用户可以处理这些事件。开发人员可以处理挂起和恢复事件,并相应地处理应用程序状态信息。
处理挂起和恢复事件的代码片段。
public App() {
this.InitializeComponent();
this.Suspending += OnSuspending;
this.Resuming += App_Resuming;
}
void App_Resuming(object sender, object e)
{
throw new NotImplementedException();
}
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
await SuspensionManager.SaveAsync();
deferral.Complete();
}
应用程序终止没有关联的事件。我们可以通过激活事件来检查应用程序是否先前已终止。验证应用程序先前状态的代码片段
protected override async void OnLaunched(LaunchActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
//Associate the frame with a SuspensionManager key
SuspensionManager.RegisterFrame(rootFrame, "AppFrame");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
// Restore the saved session state only when appropriate
try
{
await SuspensionManager.RestoreAsync();
}
catch (SuspensionManagerException)
{
//Something went wrong restoring state.
//Assume there is no state and continue
}
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
if (!rootFrame.Navigate(typeof(GroupedItemsPage), "AllGroups"))
{
throw new Exception("Failed to create initial page");
}
}
// Ensure the current window is active
Window.Current.Activate();
}
后台进程
尽管 Windows 应用商店应用的进程生命周期需要后台进程,但 Windows 8 中的后台进程存在许多限制。Windows 8 中的所有资源都分配给前台进程,并允许后台进程有限地访问各种资源。
后台进程可以是服务器端的,例如磁贴推送通知,也可以是客户端的,例如后台音频播放、锁屏应用等。在本文中,我们将通过后台任务、后台音频播放和锁屏应用来研究客户端后台进程的实现。
后台进程的运行与主应用程序是运行、挂起还是终止状态无关。
图2:后台进程生命周期
后台任务实现
要实现后台任务,首先创建一个将作为前台应用程序的主应用程序。对于我们的示例场景,我将使用一个使用 WCF 服务向数据库插入几条记录的应用程序。
图3:主应用程序截图
后台任务是我们在不将应用程序带到前台的情况下执行后台操作的方式。要定义后台任务,我们需要定义一个 WinRT 组件,其中任务类实现 IBackgroundTask 接口。此接口有一个方法 Run,用于执行后台操作。
图4:WinRT 组件创建
注意:如果我们在普通的类库项目中定义了该类,那么后台任务将无法工作。
示例后台任务
我们的主应用程序将使用 WCF 服务将一条记录插入数据库。后台任务以固定的时间间隔轮询数据库,或依赖于指定的条件,查看表中是否有新记录。如果有新记录,则处理新数据。
using Windows.ApplicationModel.Background;
namespace MyBackgroundTask
{
public sealed class MyTask:IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
SampleSvc.Service1Client obj = new SampleSvc.Service1Client();
obj.ProcessDetailsAsync();
}
}
}
注册后台任务
将后台任务项目添加到主应用程序的引用中。现在,通过将其与触发器和条件关联,在主应用程序中注册后台任务。
触发器
触发器指示任务何时执行,并且有许多系统定义的触发器,如 TimeTrigger、MaintenanceTrigger 等。前台应用程序向系统注册触发器,当触发器发生时,系统将在应用程序容器内激活后台任务。对于我们的示例场景,我们需要后台任务根据 Internet 可用触发器执行,以触发后台进程执行。
条件
条件定义了执行任务的条件,并且是可选的。即使触发器启动了后台任务,如果条件为 false,后台任务也不会执行任何代码。一旦条件变为 true,它就开始执行任务。有系统定义的条件,如 InternetAvailable、UserNotPresent 等。对于我们的示例场景,我们将用户存在作为条件。即使 Internet 可用,如果用户已锁定或另一位用户已登录系统,后台任务也不会执行。
图5:触发器和条件
与我们的主应用程序一起注册后台任务的代码片段如下所示
IBackgroundTaskRegistration task;
BackgroundTaskBuilder obj = new BackgroundTaskBuilder();
obj.Name = "MyBackgroundTask.MyTask";
obj.TaskEntryPoint = "MyBackgroundTask.MyTask";
SystemTrigger internetAvailable = new SystemTrigger(SystemTriggerType.InternetAvailable, false);
SystemCondition userCondition = new SystemCondition(SystemConditionType.UserPresent);
obj.SetTrigger(internetAvailable);
obj.AddCondition(userCondition);
task = obj.Register();
与任何 Windows 8 应用程序关联的功能或附加功能需要在应用程序清单文件中指定。现在,我们在主应用程序的清单文件中定义后台任务。打开 Package.manifest 文件,然后转到声明部分。从列表中添加后台任务。选择与后台任务关联的触发器。在应用程序设置下,将入口点设置为后台任务,即我们实现 IBackgroundTask 接口的类。
图6:清单中的后台任务声明
进度信息
主应用程序可以通过设置后台任务类中 IBackgroundTaskInstace 的 Progress 属性来监视后台任务的进度。为了在主应用程序中获得及时更新,请注册 IBackgroundTaskRegistration 的 Progress 和 Completed 事件。
从后台任务传递进度信息的示例代码片段
public void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.Progress = 0;
SampleSvc.Service1Client obj = new SampleSvc.Service1Client();
taskInstance.Progress = 20;
obj.ProcessDetailsAsync();
taskInstance.Progress = 100;
}
在主应用程序中处理进度和完成事件的示例代码片段
BackgroundTaskRegistration task = obj.Register();
task.Progress += task_Progress;
task.Completed += task_Completed;
-----------------------------------
void task_Completed(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args)
{
status.Text = "Completed";
}
void task_Progress(BackgroundTaskRegistration sender, BackgroundTaskProgressEventArgs args)
{
status.Text= "Progress - " + args.Progress +" %";
}
后台任务已在内存中注册,并且在主应用程序挂起后仍然有效。一旦主应用程序终止,后台任务需要重新注册。要重新注册,请使用 BackgroundTaskregistration.AllTasks 验证后台任务是否存在。
如果我们不验证后台任务的存在而直接注册,那么您会发现具有相同名称的多个后台任务正在注册。
图7:同一后台任务的多次注册
在注册后台任务之前验证其是否存在。
IBackgroundTaskRegistration task;
if (BackgroundTaskRegistration.AllTasks.Count(t => t.Value.Name == "MyBackgroundTask.MyTask") ==0)
{
BackgroundTaskBuilder obj = new BackgroundTaskBuilder();
obj.Name = "MyBackgroundTask.MyTask";
obj.TaskEntryPoint = "MyBackgroundTask.MyTask";
SystemTrigger internetAvailable = new SystemTrigger(SystemTriggerType.InternetAvailable, false);
SystemCondition userCondition = new SystemCondition(SystemConditionType.UserPresent);
obj.SetTrigger(internetAvailable);
obj.AddCondition(userCondition);
task = obj.Register();
}
else
{
task=BackgroundTaskRegistration.AllTasks.Where(t => t.Value.Name == "MyBackgroundTask.MyTask").First().Value;
}
task.Progress += task_Progress;
task.Completed += task_Completed;
集成后台任务与前台
前台应用程序和后台任务使用相同的应用程序设置,包括本地和漫游设置。前台应用程序和后台任务之间的通信通过应用程序设置进行。
var localSetting =ApplicationData.Current.LocalSettings;
localSetting.Values["data"] = "Sample Data";
------------------------------------------
Object returnData = localSetting.Values["data"];
测试和调试后台任务
要调试后台任务,请先启动主应用程序。一旦主应用程序在前台开始工作,切换到 Visual Studio。在调试选项下,选择后台任务名称以开始调试后台任务。
图8:调试后台任务
注意:- 上述调试选项属于“调试位置”工具栏
------------------------------------------------------------------------------------------------------------------------
错误:- 开始调试时,您可能会收到以下错误消息。请在两个地方验证提到的后台进程任务
-入口点属性在程序包清单文件中指定
-主应用程序在注册后台任务时指定的入口点
图9:后台任务调试问题
另一个选项是在事件查看器 -> 应用程序和服务日志 -> Microsoft -> Windows -> BackgroundTaskInfrastructure 下启用诊断日志
------------------------------------------------------------------------------------------------------------------------
一旦上述问题解决,断点就会正确命中。
图10:后台任务调试
锁屏应用
使用 Windows 8 应用商店应用,我们可以在锁屏界面上显示一些状态信息。锁屏功能在移动应用程序中尤其有用,因为设备大部分时间都会被锁定。Windows 8 锁屏界面包括背景图片、日期和时间、电池电量指示器和网络状态。应用程序可以在锁屏界面上显示其徽章、实时磁贴的最新磁贴通知或弹出通知。我们最多可以在锁屏界面上显示 7 个应用程序。其中 7 个,一个显示文本,其余的可以显示徽章或弹出通知。
徽章表示 0 到 99 的数字或一个图标,表示收到的新电子邮件、新的 Twitter 消息数、股市上涨或下跌等。磁贴通知是显示最近新闻、当前市场价值等的简短文本。弹出通知是特殊的通知,出现在屏幕的右上角,会在指定的时间间隔内保留在屏幕上。这将是状态更新或需要用户干预的操作。
当用户将应用程序放置在锁屏界面上时,表示用户希望从应用程序中看到实时信息。锁屏界面显示应用程序开始屏幕磁贴中的数据。如果磁贴包含长文本或不是实时数据,那么该应用程序可能不是锁屏界面的理想选择。
应用程序应在清单文件中声明锁屏功能。我们可以在清单文件中选择徽章或徽章和磁贴文本选项。如果是徽章,则应用程序将显示徽章图标以及徽章编号。否则,它使用清单中指定的宽幅图标显示徽章和磁贴文本。
打开清单文件,转到应用程序 UI 选项卡。在通知部分指定徽章图标和锁屏通知。
图11:锁屏声明
要显示锁屏信息,应用程序必须在声明中声明后台任务。锁屏应用支持的后台任务有控制通道、计时器和推送通知。
图12:后台任务声明
使用磁贴通知从应用程序发送徽章更新通知。我们可以指定 0 到 99 的数字或可用、警报等图标名称作为徽章值。
XmlDocument badgeXml = new XmlDocument();
badgeXml.LoadXml("<badge value=\"88\" />");
BadgeNotification badge = new BadgeNotification(badgeXml);
BadgeUpdateManager.CreateBadgeUpdaterForApplication().Update(badge);
有两种方法可以启用锁屏应用在锁屏界面上显示。一种方法是使用“Background.BackgroundExecutionManager.RequestAccessAsync”方法请求用户将应用程序添加到锁屏界面。这会向用户显示一个对话框,请求将应用程序添加到锁屏界面。或者,用户需要通过 PC 设置手动启用它。用户可以通过 PC 设置完全控制删除锁屏应用程序。
图13:启用锁屏应用
结论
后台任务在 Windows 8 应用商店应用程序开发中发挥着重要作用。Windows 8 重新定义了应用程序与系统和用户交互的方式。由于显示的后台应用程序数量有限,以及实时磁贴和锁屏应用的概念,许多应用程序都需要后台任务。