App Service 是一种背景工作运行的服务,提供给其他Apps 使用就像Web Service。它本身无使用介面(UI-less),允许Apps 在同一个设备被引用,甚至Windows 10 1607 开始允许remote devices 使用它。

[ 重点观念 ]

Windows 10, version 1607 开始, App Service 支持新模式:
可以与host App 运行在相同的process;(一般属于Background Task 执行在不同的process)
支援从App呼叫Remote Devices中的App Service;
想要App Service每次被启动都是新的instance,在Package.appmanifest加入宣告;uap4:SupportsMultipleInstances="true";但需要Windows 10, version 15063以上才支援
App Service 的生命周期,因为Process 有所不同:
后台任务(进程外):
当它被建立时会进入Run(),随着Run()执行完毕就会被结束
它被启动后,基本会维持活着约有30秒,可搭配呼叫GetDeferral()多加5秒来完成任务
In-app process model:生命周期则跟着呼叫者一起共存,让两个Apps 之间更容易沟通,不用再分成两份code 来串联与维护
App Service 的OnTaskCancel() 被触发有几个原因:
Client app释放AppServiceConnection
Client app 被 suspended
系统关闭或睡眠
系统执行该Task 用过高的资源
大略有概念之后,接着介绍怎么做基本的App Service (two process),再介绍怎么整合到App 的process 里面;

  • 如何建立App service 并使用它:

分成两个App 做说明:一个是拥有App Service 的Host App;一个是使用App Service 的Client App;

1建立一个Windows Runtime Component,并且加入AppServiceConnection 的处理逻辑:

public sealed class ServiceTask : IBackgroundTask
{
private BackgroundTaskDeferral backgroundTaskDeferral;
private AppServiceConnection appServiceconnection; public void Run(IBackgroundTaskInstance taskInstance)
{
// Background Task 被建立時,取得 deferral 拉長生命周期,避免被結束
this.backgroundTaskDeferral = taskInstance.GetDeferral(); // 一定要註冊處理 Canceled 事件來正確釋放用到的資源
taskInstance.Canceled += OnTaskCanceled; // 根據被啓動的 Instance 類型,建立 App Service Connection,並註冊 Request 事件.
var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
appServiceconnection = details.AppServiceConnection;
appServiceconnection.RequestReceived += OnRequestReceived;
} private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
if (this.backgroundTaskDeferral != null)
{
// Complete the service deferral.
this.backgroundTaskDeferral.Complete();
}
} private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
// 當 App Service 收到請求時,該 method 就會被觸發
// 先要求取得 取得 deferral 拉長生命周期
var requestDeferral = args.GetDeferral(); ValueSet message = args.Request.Message;
string cmd = message["cmd"] as string;
string id = message["id"] as string; ValueSet responseMsg = new ValueSet(); switch (cmd)
{
case "Query":
responseMsg.Add("id", "123456");
responseMsg.Add("name", "pou");
responseMsg.Add("status", "OK");
var result = await args.Request.SendResponseAsync(responseMsg);
break;
} requestDeferral.Complete();
}
}

2在Host App 的Package.manifest 宣告App Service 并设定Entry Point,记得把App Service 的专案加入到Host App 的专案参考:

<Applications>
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="ServiceHost.App">
<uap:VisualElements />
<Extensions>
<uap:Extension Category="windows.appService" EntryPoint="MyAppService.ServiceTask">
<uap:AppService Name="com.pou.MyApService" />
</uap:Extension>
</Extensions>
</Application>
</Applications>

加入专案参考这样在Host App被安装的时候才会一并加入App Service。利用Windows.ApplicationModel.Package.Current.Id.FamilyName在Host App拿到package family name,准备交给Client App。
3在 Client App 利用 AppServiceConnection 呼叫 App Service:

private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
AppServiceConnection connection = new AppServiceConnection();
connection.AppServiceName = "com.pou.MyApService";
connection.PackageFamilyName = "f9842749-e4c8-4c15-bac8-bc018db1b2ea_s1mb6h805jdtj"; var status = await connection.OpenAsync(); if (status != AppServiceConnectionStatus.Success)
{
Debug.WriteLine("Failed to connect");
return;
} var message = new ValueSet();
message.Add("cmd", "Query");
message.Add("id", "1234"); AppServiceResponse response = await connection.SendMessageAsync(message);
string result = ""; if (response.Status == AppServiceResponseStatus.Success)
{
if (response.Message["status"] as string == "OK")
{
result = response.Message["name"] as string;
}
}
}

上面介绍的App Service 是比较一般的用法, 把App Service 放到Background Task 的架构。

  • 把App Service 合并到App.xaml.cs 里面,作为Same Process:

AppServiceConnection允许其他App叫醒在背景中自己的App并传入指令。它与上方的out-of-process最大不同有两个:

1Package.manifest 宣告 <uap:Extension Category="windows.appService"> 不用 Entry Point,改用 OnBackgroundActivated()。

<Package>
<Applications>
<Application>
<Extensions>
<uap:Extension Category="windows.appService">
<uap:AppService Name="com.pou.MyApService" />
</uap:Extension>
</Extensions>
</Application>
</Applications>

2在App.xaml.cs加入OnBackgroundActivated()的处理逻辑。

sealed partial class App : Application
{
private AppServiceConnection appServiceConnection;
private BackgroundTaskDeferral appServiceDeferral; protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
base.OnBackgroundActivated(args); AppServiceTriggerDetails appService = args.TaskInstance.TriggerDetails as AppServiceTriggerDetails; if (appService ==null)
{
return;
} args.TaskInstance.Canceled += OnAppServicesCanceled; // appServiceDeferral 與 appServiceConnection 需要變成公用變數
// 因爲其他時間需要用到,已維持連線的一致性
appServiceDeferral = args.TaskInstance.GetDeferral();
appServiceConnection = appService.AppServiceConnection; appServiceConnection.RequestReceived += AppServiceConnection_RequestReceived;
appServiceConnection.ServiceClosed += AppServiceConnection_ServiceClosed;
} private async void AppServiceConnection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
// 當 App Service 收到請求時,該 method 就會被觸發 // 先要求取得 取得 deferral 拉長生命周期
var requestDeferral = args.GetDeferral(); ValueSet message = args.Request.Message; string cmd = message["cmd"] as string;
string id = message["id"] as string; ValueSet responseMsg = new ValueSet(); switch (cmd)
{
case "Query":
responseMsg.Add("id", "123456");
responseMsg.Add("name", "pou");
responseMsg.Add("status", "OK");
var result = await args.Request.SendResponseAsync(responseMsg);
break;
} requestDeferral.Complete();
} private void AppServiceConnection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
{
appServiceDeferral?.Complete();
appServiceConnection?.Dispose();
} private void OnAppServicesCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
appServiceDeferral?.Complete();
appServiceConnection?.Dispose();
}
}

要支援in-process model就是这样简单,而且让原本的App Service逻辑回到App本身,让逻辑更干净。OnBackgroundActivated()负责处理App Service的启用,并储存Deferral保持服务的生命周期,详细可以参考Windows 10通用Windows平台(UWP) app周期。

UWP - 介绍App Service 与新功能的更多相关文章

  1. 从淘宝 UWP 的新功能 -- 比较页面来谈谈 UWP 的窗口多开功能

    前言 之前在 剁手党也有春天 -- 淘宝 UWP ”比较“功能诞生记 这篇随笔中介绍了一下 UWP 淘宝的“比较”新功能呱呱坠地的过程.在鲜活的文字背后,其实都是程序员不眠不休的血泪史(有血有泪有史) ...

  2. Android 9 新功能 及 API 介绍(提供了实用的模块化的功能支持,包括 人工智能)

      Android 9(API 级别 28)为用户和开发者引入了众多新特性和新功能. 本文重点介绍面向开发者的新功能. 要了解新 API,请阅读 API 差异报告或访问 Android API 参考. ...

  3. Java 14 新功能介绍

    不做标题党,认认真真写个文章. 文章已经收录在 Github.com/niumoo/JavaNotes 和未读代码博客,点关注,不迷路. Java 14 早在 2019 年 9 月就已经发布,虽然不是 ...

  4. Redis4.0支持的新功能说明

    本文以华为云DCS for Redis版本为例,介绍Redis4.0的新功能.文章转载自华为云帮助中心. 与Redis3.x版本相比,DCS的Redis4.x以上版本,除了开源Redis增加的特性之外 ...

  5. WSS存储服务器(Windows Storage Server) 2012新功能解析

    虽然最近一段时间有关微软的新闻大多数集中在Windows 8以及Surface平板设备身上,但数周之前Windows Server 2012新版本中所包含的Windows Storage Server ...

  6. LightningChart最新版 v.8.3 全新发布,新功能使用教程。

    LightningChart最新版v.8.3全新发布,主要介绍以下五个新功能及使用教程.   1. 网格模型,三角鼠标追踪 Tracing MeshModels with mouse. Traced ...

  7. Java 11 新功能来了!

    关键时刻,第一时间送达! 目前 Oracle 已经发布了 Java Development Kit 10,下个版本 JDK 11 也即将发布.本文介绍 Java 11 的新功能. 根据Oracle新出 ...

  8. Java 11新功能抢先了解

    目前 Oracle 已经发布了 Java Development Kit 10,下个版本 JDK 11 也即将发布.本文介绍 Java 11 的新功能. 根据Oracle新出台的每6个月发布一次Jav ...

  9. TFS 2015新功能之一,当前迭代查询标记

    TFS 2015发布在即,有幸作为MVP提前获得了TFS的RTM版本,下面就TFS 2015的新功能做一些介绍:   TFS 2015新功能之一,当前迭代查询标记 在TFS的查询中,可以将" ...

随机推荐

  1. python 常用命令sys.exit()

    Python的程序有两中退出方式:os._exit(), sys.exit() os._exit()会直接将python程序终止,之后的所有代码都不会继续执行. sys.exit()会引发一个异常:S ...

  2. 两人团队项目-石家庄地铁查询系统(web版)psp表

    结对开发_石家庄地铁查询_博客地址:https://www.cnblogs.com/Aduorisk/p/10652917.html 队友:冯利伟 PSP: PSP0 Personal Softwar ...

  3. 前端性能优化实践-gzip

    一名优秀的前端工程师必备技能之一就是要会性能监控,并且能相应的进行性能优化.最近,有需求将项目做一些优化,提升用户的体验.看了一下项目并没有开启gzip,于是着手实现gzip压缩,下面就是具体的实践过 ...

  4. Jmeter性能测试指标分析

    一.Aggregate Report 是 JMeter 常用的一个 Listener,中文被翻译为"聚合报告 如果大家都是做Web应用的性能测试,例如访问百度请求为例,线程10,循环10次, ...

  5. MYSQL时间戳和日期相互转换 笔记整理

    相关函数: date_format(date, format) 函数,MySQL日期格式化函数date_format() unix_timestamp() 函数 str_to_date(str, fo ...

  6. P3203 弹飞绵羊-分块

    P3203 弹飞绵羊-分块 观察数据范围,发现可以分块.只需要处理每个点跳出所在块后的位置和次数即可.目的是为了加速查询并降低修改复杂度. 对于修改,重构整个块内信息即可. 时间复杂度正确的一批 具体 ...

  7. xshell中操作服务器笔记

    sudo su 获取root权限 cd 切换到相应文件夹 ll ls 查看文件夹内容 cp file folder 复制文件到文件夹 \cp为强制覆盖不提示 cp -r /packageA/* /cp ...

  8. 自学linux——11.shell入门

    shell 基础 1.shell介绍(内置脚本) 程序开发的效率非常高,依赖于功能强大的命令可以迅速地完成开发任务(批处理) 语法简单,代码写起来比较轻松,简单易学 (1)什么是shell shell ...

  9. 解决 OnDropFiles 可能无响应的问题【转】

    大多数程序都有接收拖放文件的功能,即是用鼠标把文件拖放到程序窗口上方,符合格式的文件就会自动被程序打开.最近自己对编写的程序增加了一个拖放文件的功能,在 Windows XP.Windows Serv ...

  10. promise详解 : 实现promise(附实现代码)

    promise then 的特点 : then 函数的返回值是一个 promise, 可以继续调用 then 函数 回调函数 resolve 和 reject 的参数 value /reason, 可 ...