UWP - 介绍App Service 与新功能
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 与新功能的更多相关文章
- 从淘宝 UWP 的新功能 -- 比较页面来谈谈 UWP 的窗口多开功能
前言 之前在 剁手党也有春天 -- 淘宝 UWP ”比较“功能诞生记 这篇随笔中介绍了一下 UWP 淘宝的“比较”新功能呱呱坠地的过程.在鲜活的文字背后,其实都是程序员不眠不休的血泪史(有血有泪有史) ...
- Android 9 新功能 及 API 介绍(提供了实用的模块化的功能支持,包括 人工智能)
Android 9(API 级别 28)为用户和开发者引入了众多新特性和新功能. 本文重点介绍面向开发者的新功能. 要了解新 API,请阅读 API 差异报告或访问 Android API 参考. ...
- Java 14 新功能介绍
不做标题党,认认真真写个文章. 文章已经收录在 Github.com/niumoo/JavaNotes 和未读代码博客,点关注,不迷路. Java 14 早在 2019 年 9 月就已经发布,虽然不是 ...
- Redis4.0支持的新功能说明
本文以华为云DCS for Redis版本为例,介绍Redis4.0的新功能.文章转载自华为云帮助中心. 与Redis3.x版本相比,DCS的Redis4.x以上版本,除了开源Redis增加的特性之外 ...
- WSS存储服务器(Windows Storage Server) 2012新功能解析
虽然最近一段时间有关微软的新闻大多数集中在Windows 8以及Surface平板设备身上,但数周之前Windows Server 2012新版本中所包含的Windows Storage Server ...
- LightningChart最新版 v.8.3 全新发布,新功能使用教程。
LightningChart最新版v.8.3全新发布,主要介绍以下五个新功能及使用教程. 1. 网格模型,三角鼠标追踪 Tracing MeshModels with mouse. Traced ...
- Java 11 新功能来了!
关键时刻,第一时间送达! 目前 Oracle 已经发布了 Java Development Kit 10,下个版本 JDK 11 也即将发布.本文介绍 Java 11 的新功能. 根据Oracle新出 ...
- Java 11新功能抢先了解
目前 Oracle 已经发布了 Java Development Kit 10,下个版本 JDK 11 也即将发布.本文介绍 Java 11 的新功能. 根据Oracle新出台的每6个月发布一次Jav ...
- TFS 2015新功能之一,当前迭代查询标记
TFS 2015发布在即,有幸作为MVP提前获得了TFS的RTM版本,下面就TFS 2015的新功能做一些介绍: TFS 2015新功能之一,当前迭代查询标记 在TFS的查询中,可以将" ...
随机推荐
- python 常用命令sys.exit()
Python的程序有两中退出方式:os._exit(), sys.exit() os._exit()会直接将python程序终止,之后的所有代码都不会继续执行. sys.exit()会引发一个异常:S ...
- 两人团队项目-石家庄地铁查询系统(web版)psp表
结对开发_石家庄地铁查询_博客地址:https://www.cnblogs.com/Aduorisk/p/10652917.html 队友:冯利伟 PSP: PSP0 Personal Softwar ...
- 前端性能优化实践-gzip
一名优秀的前端工程师必备技能之一就是要会性能监控,并且能相应的进行性能优化.最近,有需求将项目做一些优化,提升用户的体验.看了一下项目并没有开启gzip,于是着手实现gzip压缩,下面就是具体的实践过 ...
- Jmeter性能测试指标分析
一.Aggregate Report 是 JMeter 常用的一个 Listener,中文被翻译为"聚合报告 如果大家都是做Web应用的性能测试,例如访问百度请求为例,线程10,循环10次, ...
- MYSQL时间戳和日期相互转换 笔记整理
相关函数: date_format(date, format) 函数,MySQL日期格式化函数date_format() unix_timestamp() 函数 str_to_date(str, fo ...
- P3203 弹飞绵羊-分块
P3203 弹飞绵羊-分块 观察数据范围,发现可以分块.只需要处理每个点跳出所在块后的位置和次数即可.目的是为了加速查询并降低修改复杂度. 对于修改,重构整个块内信息即可. 时间复杂度正确的一批 具体 ...
- xshell中操作服务器笔记
sudo su 获取root权限 cd 切换到相应文件夹 ll ls 查看文件夹内容 cp file folder 复制文件到文件夹 \cp为强制覆盖不提示 cp -r /packageA/* /cp ...
- 自学linux——11.shell入门
shell 基础 1.shell介绍(内置脚本) 程序开发的效率非常高,依赖于功能强大的命令可以迅速地完成开发任务(批处理) 语法简单,代码写起来比较轻松,简单易学 (1)什么是shell shell ...
- 解决 OnDropFiles 可能无响应的问题【转】
大多数程序都有接收拖放文件的功能,即是用鼠标把文件拖放到程序窗口上方,符合格式的文件就会自动被程序打开.最近自己对编写的程序增加了一个拖放文件的功能,在 Windows XP.Windows Serv ...
- promise详解 : 实现promise(附实现代码)
promise then 的特点 : then 函数的返回值是一个 promise, 可以继续调用 then 函数 回调函数 resolve 和 reject 的参数 value /reason, 可 ...