在以往版本中,后台任务都是以独立的专用进程来运行,因此,定义后台任务代码的类型都要位于 Windows 运行时组件项目中。

不过,在14393中,SDK 作了相应的扩展,不仅支持以前的独立进程中运行后台任务,也允许后台任务与应用程序位于同一个进程中执行,即单进程后台任务(Single – Process)。

听起来很高深?其实很Easy,和以往的多进程模式的后台任务差不多,只是有以下两点不同:

  1. 对于独立进程的后台任务,实现方法是实现 IBackgroundTask 接口,然后实现 Run 方法;而如果你希望让后台任务在应用所在的进程中执行,可以重写 Application 类的 OnBackgroundActivated 方法就可以了,它类似于 IBackgroundTask 的 Run 方法。在OnBackgroundActivated方法中,你可以通过方法参数获得一个IBackgroundTaskInstance实例,所以与Run方法的处理是一样的。
  2. 在配置清单文件时,独立进程中执行的后台任务是必须指明入口点的,即后台任务类的类型名,包含命名空间路径。而如果后台任务是在应用进程中执行的话,就不需要指点入口点,因为后台任务的入口点与应用相同,就是App类。

只要明白了以上两点,你就明白了95%了,剩下的5%,就等老周来演示给大伙瞧吧。

App Service 的实现跟后台任务差不多,本次表演,老周就选用AppService来试水吧。

这个示例只有小学二年级水平,它分为两个应用,一个应用具备app service,另一个应用调用它。service的功能是计算两个整数的乘积,所以说是小学二年级水平。

先看app service的应用实现,项目模板会为我们生成一个App类,基类是Application,很简单,直接重写OnBackgroundActivated方法就行了。

        protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
……
}

这个方法就相当于Run方法,所以,和以前一样,在其中添加处理代码。

            IBackgroundTaskInstance taskInstance = args.TaskInstance;
var taskDef = taskInstance.GetDeferral();
taskInstance.Canceled += (ca, cb) => taskDef.Complete(); if (taskInstance.TriggerDetails != null && taskInstance.TriggerDetails is AppServiceTriggerDetails)
{
AppServiceTriggerDetails details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
string appsvName = details.Name;
if (appsvName == "my.multip")
{
AppServiceConnection conn = details.AppServiceConnection;
conn.RequestReceived += async (r1, r2) =>
{
var svdef = r2.GetDeferral();
var request = r2.Request;
ValueSet inputs = request.Message;
int x = Convert.ToInt32(inputs["a"]);
int y = Convert.ToInt32(inputs["b"]);
int o = x * y;
ValueSet sendBack = new ValueSet();
sendBack["r"] = o;
await request.SendResponseAsync(sendBack);
svdef.Complete();
taskDef.Complete();
};
conn.ServiceClosed += (k1, k2) =>
{
Debug.WriteLine("app service连接关闭。");
taskDef.Complete();
};
}
}

然后就完事了,注意在清单文件中,不要指定入口点了。

      <Extensions>
<uap:Extension Category="windows.appService">
<uap:AppService Name="my.multip" />
</uap:Extension>
</Extensions>

现在可以在另一个应用中调用了。

            AppServiceConnection conn = new AppServiceConnection();
conn.AppServiceName = "my.multip";
conn.PackageFamilyName = txtPkname.Text;
var state = await conn.OpenAsync();
if (state == AppServiceConnectionStatus.Success)
{
ValueSet input = new ValueSet();
input["a"] = ComputeObject.Num1;
input["b"] = ComputeObject.Num2;
var response = await conn.SendMessageAsync(input);
if (response.Status == AppServiceResponseStatus.Success)
{
ValueSet res = response.Message;
ComputeObject.Result = Convert.ToInt32(res["r"]);
}
}

调用App Service 时,先new一个AppServiceConnection,然后指定包含app service的应用的Package的名字,这个包名可以用以下方法来获取:

  • 在包含app service的应用中,访问这个静态属性获取:Windows.ApplicationModel.Package.Current.Id.FamilyName。
  • 用VS生成项目,然后打开【输出】窗口,显示来源选择“生成”,这样你就能看到包含应用服务的应用包名了。如下图。

不能使用清单文件中的包名,因为那个包名不完整。不过,你得注意了,通过【输出】窗口获取包名的时候,包的名字中要去掉版本号和平台描述,比如,我的项目中输出的生成的包名为:

62da1ba5-7faf-4109-b82a-7a6027dbc3a3_1.0.0.0_x86__6pcpwfmxf0rfc

其中,1.0.0.0是版本号,要去掉,x86是平台描述,也要干掉,后面的6pcpwfmxf0rfc可能是开发者的标识,不能去掉。最终得到需要的包名为:

62da1ba5-7faf-4109-b82a-7a6027dbc3a3_6pcpwfmxf0rfc

前面的GUID是应用包名字,后面要接一个下划线,然后是6pcpwfmxf0rfc。

把这个最终取得的名字赋值给AppServiceConnection的PackageFamilyName属性即可,AppServiceName属性表示要调用的app service的名字。

准备好参数后,调用OpenAsync方法打开连接,一定要先打开连接,才能调用应用服务。使用SendMessageAsync方法发送输入参数,参数是一个ValueSet对象,其实是个字典,可以自定义参数结构。在本例中,既然要计算乘法运算,当然是要传递两个整数值了。

SendMessageAsync方法调用后,会异步返回一个AppServiceResponse实例,该实例中包含着一些从应用服务返回的内容,访问Message属性就得到应用服务响应的ValueSet,并可从中取出需要的数据,该例子中,是取出计算结果。

好,项目干完了,咱们来试试,同时运行两个应用,然后试着调用一下应用服务。

效果已达到, 这时候,大伙可能会疑惑,如果包含app serivce的应用进程退出后,还能调用应用服务吗?没事,许多事情就是试出来的,试试看。把包含应用服务的应用进程结束掉,然后再调用一次,发现是可以成功调用的。

有了这一招,定义后台任务就灵活很多了,既可以在独立进程中完成,也可以在应用进程中完成,具体采用哪一种,就看实际情况了。一切东西都是灵活运用的,千万不要把技术学死了。那些整天吃饱了撑着,想把什么东西都变成公式化的思想是幼稚的、死板的,这个世界上,不可以量化的事情多得很。

不过,老周可以发表一些低见,仅作参考。如果后台任务的触发源与应用程序关系不大,比如用户登录/注销时执行的,每隔一段时间执行的(定时),这些情况,建议把后台任务写到独立的Windows运行时组件项目中,让它以独立的进程进行。

要是后台任务是应用程序主动触发的,比如后台转码(音/视频处理),或者由应用程序使用Application Trigger触发的后台任务,都可以考虑把它归入应用程序进程中,即本文所讲述的情况。

好了,今天的牛逼吹完了,该去喝点茶了(白开水最好喝,集天地灵气,无杂质,无负作用),下一篇文章咱们聊聊预启动的事情。

示例源代码下载

【Win 10 应用开发】在App所在的进程中执行后台任务的更多相关文章

  1. 【Win 10 应用开发】RTM版的UAP项目解剖

    Windows 10 发布后,其实SDK也偷偷地在VS的自定义安装列表中出现了,今天开发人员中心也更新了下载.正式版的SDK在API结构上和以前预览的时候是一样的,只是版本变成10240罢了,所以大家 ...

  2. 【Win 10 应用开发】导入.pfx证书

    这个功能其实并不常用,一般开发较少涉及到证书,不过,简单了解一下还是有必要的. 先来说说制作测试证书的方法,这里老周讲两种方法,可以生成用于测试的.pfx文件. 产生证书,大家都知道有个makecer ...

  3. 【Win 10应用开发】多窗口视图

    Windows App一般情况下,同一时刻只能有一个应用程序实例在运行,为了在特殊需求下可以同时呈现不同的UI,SDK提供了多视图操作支持. 应用程序可以创建新的应用视图,以新的视图为基础可以呈现与主 ...

  4. 【Win 10应用开发】Adaptive磁贴模板的XML文档结构

    在若干天之前,老周给大家讲了Adaptive Toast通知的XML模板,所以相应地,今天老周给大家介绍一下Adaptive磁贴的新XML模板. 同样道理,你依旧可以使用8.1时候的磁贴模板,在win ...

  5. 【Win 10应用开发】认识一下UAP项目

    Windows 10 SDK预览版需要10030以上版本号的Win 10预览版系统才能使用.之前我安装的9926的系统,然后安装VS 2015 CTP 6,再装Win 10 SDK,但是在新建项目后, ...

  6. 【Win 10 应用开发】启动远程设备上的应用

    这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用.激活远程应用需要以下前提: 系统必须是build 14393 ...

  7. 【Win 10 应用开发】Toast通知激活应用——前台&后台

    老周最近热衷于讲故事,接下来还是讲故事时间. 有人问我:你上大学的时候,有加入过学生会吗?读大学有没有必要加入学生会? 哎哟,这怎么回答呢,从短期来说,加入学生会有点用,至少可以娱乐一下,运气好的话, ...

  8. 【Win 10 应用开发】在代码中加载文本资源

    记得前一次,老周给大伙,不,小伙伴们介绍了如何填写 .resw 文件,并且在 XAML 中使用 x:Uid 标记来加载.也顺便给大伙儿分析了运行时是如何解析 .resw 文件的. 本来说好了,后续老周 ...

  9. 【Win 10应用开发】延迟共享

    延迟共享是啥呢,这么说吧,就是在应用程序打开共享面板选择共享目标时,不会设置要共享的数据,而是等到共享目标请求数据时,才会发送数据,而且,延迟操作可以在后台进行. 这样说似乎过于抽象,最好的诠释方法, ...

随机推荐

  1. .Net Core MVC 网站开发(Ninesky) 2.3、项目架构调整(续)-使用配置文件动态注入

    上次实现了依赖注入,但是web项目必须要引用业务逻辑层和数据存储层的实现,项目解耦并不完全:另一方面,要同时注入业务逻辑层和数据访问层,注入的服务直接写在Startup中显得非常臃肿.理想的方式是,w ...

  2. 深入node之Transform

    Transform流特性 在开发中直接接触Transform流的情况不是很多,往往是使用相对成熟的模块或者封装的API来完成流的处理,最为特殊的莫过于through2模块和gulp流操作.那么,Tra ...

  3. 深入浅出JavaScript之闭包(Closure)

    闭包(closure)是掌握Javascript从人门到深入一个非常重要的门槛,它是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.下面写下我的学习笔记~ 闭包-无处不 ...

  4. 使用蓝灯后,IE浏览器以及内置IE浏览器的程序不能使用的解决方案

    使用完蓝灯后,每次使用IE浏览器都不能正常使用,于是有了下面的这个方案 1.通过Win+R 打开注册表编辑器(regedit) 进入目录 HKEY_CURRENT_USER \ Software \ ...

  5. linux centos中添加删除修改环境变量,设置java环境变量

    前言 安装完软件必要添加环境变量.指令很少,然而长时间不写就会不自信:我写的对吗?于是百度开始,于是发现又是各有千秋.好吧,好记星不如烂笔头.当然,最重要的是,百度出来的都他妈的是如何添加环境变量,只 ...

  6. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

  7. C语言中如何判断文件是否存在

    方法一:access函数判断文件夹或者文件是否存在 函数原型: int access(const char *filename, int mode); 所属头文件:io.h filename:可以填写 ...

  8. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

  9. 张高兴的 UWP 开发笔记:汉堡菜单进阶

    不同于Windows 8应用,Windows 10引入了"汉堡菜单"这一导航模式.说具体点,就拿官方的天气应用来说,左上角三条横杠的图标外加一个SplitView控件组成的这一导航 ...

  10. Ajax.BeginForm方法 参数

    感谢博主 http://www.cnblogs.com/zzgblog/p/5454019.html toyoung 在Asp.Net的MVC中的语法,在Razor页面中使用,替代JQuery的Aja ...