上一篇我们讨论了UWP和Desktop Extension交互中,Desktop Extension执行后立即退出的场景。下图是提到的四种场景分类:

  • 执行后立即退出
  • 等待request,处理完后退出
  • 一或多个request/response周期
  • 和UWP程序相同生命周期

本篇我们讨论第二种,Desktop Extension等待request后,根据传参完成操作后退出的,短生命周期场景。该类型有以下特征:

  1. 可能存在多次的单向调用
  2. 通过request接收参数
  3. 不关心返回结果
  4. Desktop Extension等待request,完成操作后退出

该场景的示意图如下:

我们依然以Desktop Extension启动mspaint.exe和control.exe来举例。和上一篇不同的是,这次我们会通过UWP端发起的request来传递参数。

本篇Sample Code中的AppServiceHandler,以及App.xaml.cs中的OnBackgroundActivated方法。请参考《2020年的UWP(2)——In Process App Service》,相同部分不再介绍。

本篇新增的AppServiceConnectionConnectedEventArgs对象及Connected事件,是当AppServiceConnection通过OpenAsync方法成功连接时,传递当前活动的AppServiceConnection对象,以便调用SendMessageAsync等方法。

  1. public class AppServiceConnectionConnectedEventArgs : EventArgs
  2. {
  3. public AppServiceConnection Connection { get; }
  4.  
  5. public AppServiceConnectionConnectedEventArgs(AppServiceConnection connection)
  6. {
  7. Connection = connection;
  8. }
  9. }
  10.  
  11. public event EventHandler<AppServiceConnectionConnectedEventArgs> Connected;

在AppServiceHandler中的OnBackgroundActivated方法中,我们首要做的,既是通知订阅对象,有AppServiceConnection被成功Open了,请及时响应。

  1. public void OnBackgroundActivated(AppServiceTriggerDetails details)
  2. {
  3. Connected?.Invoke(this, new AppServiceConnectionConnectedEventArgs(details.AppServiceConnection));
  4. Connection = details.AppServiceConnection;
  5. Connection.RequestReceived += Connection_RequestReceived;
  6. }

订阅这个Connected事件的,一般都是Desktop Extension的发起方。比如说UWP端的某个Button。

  1. private async void ButtonLaunchApp_Click(object sender, RoutedEventArgs e)
  2. {
  3. if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
  4. {
  5. AppServiceHandler.Instance.Connected += Instance_Connected;
  6. await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
  7. }
  8. }
  9.  
  10. private async void Instance_Connected(object sender, AppServiceConnectionConnectedEventArgs e)
  11. {
  12. AppServiceHandler.Instance.Connected -= Instance_Connected;
  13. var valueSet = new ValueSet();
  14. valueSet.Add("FileName", ComboBoxFileName.SelectionBoxItem);
  15. var response = await e.Connection.SendMessageAsync(valueSet);
  16. }

之所以需要这个Connect事件,是因为通过SendMessageAsync传参,需要依赖当前活动的AppServiceConnection对象。我们正是通过Connected事件,将AppServiceConnection对象传递给订阅者,使其能够访问SendMessageAsync等方法进行数据交互。

在Instance_Connected方法中,在每次点击按钮时,均启动一个新的Desktop Extension进程。在Desktop Extension进程中,会通过OpenAsync方法来连接AppServiceConnection。之后便是由OnBackgroundActivated方法触发Connected事件,接下来就是发起request。

该场景中,Desktop Extension仅需维持一个较短的生命周期,在等到request后,根据传参完成相应操作,就可以释放资源安全退出了。对整个APP而言,既不会长期占用过多资源,也不会导致UWP端无法Suspend。

下图中的绿色叶子图标,在Desktop Extension运行时,是不会出现的。

同时我们要知道AppService的生命周期是不可控的,在UWP端程序最小化以后,Windows会在一段时间后停止AppService,AppServiceConnection也会被dispose。所以存储一个AppServiceConnection长期对象,用来和永不退出Desktop Extension通讯并不是个好主意。

以下是Desktop Extension端的部分代码,为了方便观察应用程序的行为,我在Sample中将Enrivonment.Exit给注释掉了。

  1. public async Task InitializeAsync()
  2. {
  3. Connection = new AppServiceConnection();
  4. Connection.PackageFamilyName = Package.Current.Id.FamilyName;
  5. Connection.AppServiceName = "ParameterAppService";
  6. AppServiceConnectionStatus status = await Connection.OpenAsync();
  7. if (status != AppServiceConnectionStatus.Success)
  8. {
  9. Console.WriteLine(status);
  10. }
  11. else
  12. {
  13. Console.WriteLine(status);
  14. Connection.RequestReceived += Connection_RequestReceived;
  15. }
  16. }
  17.  
  18. private void Connection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
  19. {
  20. var content = args.Request.Message["FileName"].ToString();
  21. Process.Start(content);
  22. Console.WriteLine("Will exit after received.");
  23. //Environment.Exit(0);
  24. }

本篇简单介绍了“等待request,处理完后退出”,这一UWP和Desktop Extension数据交互的场景。感谢看到这里的同学,单纯的文字其实很难讲清楚AppService的使用,还请参考Github上的实例代码,欢迎评论及提问。

UWPSamples/UWPSamples/DataExchangeUWP/ExitAfterHandleRequest at master · manupstairs/UWPSamples (github.com)

2020年的UWP(4)——UWP和等待Request的Desktop Extension的更多相关文章

  1. 2021年的UWP(6)——长生命周期Desktop Extension向UWP的反向通知

    上一篇我们讨论了UWP和Desktop Extension间的双向通讯,适用于Desktop Extension中存在用户交互的场景.本篇我们讨论最后一种情况,与前者不同的是,Desktop Exte ...

  2. 2020年的UWP(3)——UWP和desktop extension的简单交互

    上一篇<2020年的UWP(2)--In Process App Service>中我们了解了UWP和Desktop Extension可以通过AppService进行数据交互.本篇我们就 ...

  3. 2020年的UWP(5)——UWP和Desktop Extension的双向交互

    上一篇我们提到了怎么在Desktop Extension中等待并处理UWP端发出的request.在本篇中将描述UWP和Desktop Extension双向交互的场景,即存在从两端各自发出reque ...

  4. [UWP]在UWP平台中使用Lottie动画

    最近QQ影音久违的更新了,因为记得QQ影音之前体验还算不错(FFmepg的事另说),我也第一时间去官网下载体验了一下,结果发现一些有趣的事情. 是的,你没看错,QQ影音主界面上这个动画效果是使用Lot ...

  5. [UWP]涨姿势UWP源码——Unit Test

    之前我们讨论了涨姿势UWP的RSS数据源获取,以及作为文件存储到本地,再将数据转化成Model对象.这部分非UI的内容非常适合添加Unit Test.不涉及UI的话,UT写起来简单高效,很是值得投入一 ...

  6. [UWP]涨姿势UWP源码——IsolatedStorage

    前一篇涨姿势UWP源码分析从数据源着手,解释了RSS feed的获取和解析,本篇则会就数据源的保存和读取进行举例. 和之前的Windows Runtime一样,UWP采用IsolatedStorage ...

  7. [UWP]涨姿势UWP源码——RSS feed的获取和解析

    本篇开始具体分析涨姿势UWP这个APP的代码,首先从数据的源头着手,即RSS feed的获取和解析,相关的类为RssReader,所有和数据相关的操作均放在里面. 涨姿势网站提供的RSS feed地址 ...

  8. [UWP]涨姿势UWP源码——极简的RSS阅读器

    涨姿势UWP,一个开源的RSS阅读器,一个纯粹的项目,一个有道德的APP,一个脱离了低级趣味的作者,一些有益于人民的代码.骚年,还等什么,来涨点姿势吧! 该项目代码可能会引起部分人群的不适,敏感人群请 ...

  9. [UWP]涨姿势UWP源码——UI布局

    懒癌晚期兼正月里都是过年,一直拖到今天才继续更新.之前的几篇介绍了数据的来源,属于准备工作.本篇我们正式开始构建涨姿势UWP程序的UI界面. 我们这个Hello World程序比较简单,总共只有一个页 ...

随机推荐

  1. Python ( 高级 第二部)

    目录 模块和包 面向对象 部分一: 面向对象程序开发 面向对象封装: 对象的相关操作 面向对象封装: 类的相关操作 实例化的对象/ 定义的类删除公有成员属性和公有成员方法 部分二: 单继承 多继承 菱 ...

  2. 【开源】使用.Net Core和GitHub Actions实现哔哩哔哩每日自动签到、投币、领取奖励

    BiliBiliTool是一个B站自动执行任务的工具,使用.NET Core编写,通过它可以实现B站帐号的每日自动观看.分享.投币视频,获取经验,每月自动领取会员权益.自动为自己充电等功能,帮助我们轻 ...

  3. 史上最全的Kuberenetes 常用命令手册

    1.0 k8s 集群状态检查 # 查看集群信息 kubectl cluster-info systemctl status kube-apiserver systemctl status kubele ...

  4. [论文解读] 阿里DIEN整体代码结构

    [论文解读] 阿里DIEN整体代码结构 目录 [论文解读] 阿里DIEN整体代码结构 0x00 摘要 0x01 文件简介 0x02 总体架构 0x03 总体代码 0x04 模型基类 4.1 基本逻辑 ...

  5. 基于uni-app的微信小程序之分包

    作者:故事我忘了¢个人微信公众号:程序猿的月光宝盒 目录 0. 缘由 1. 关于分包 1.0 这是 官方文档 1.1 注意事项 2.使用方法 2.1 首先你得有个uniapp的微信小程序项目 2.2 ...

  6. Python 3.9就要来了......,令人兴奋的时刻

    本文主要介绍Python3.9的一些新特性,如:更快速的进程释放,性能的提升,简便的新字符串函数,字典并集运算符以及更兼容稳定的内部API,详细如下: 字典并集和可迭代更新 字符串方法 类型提示 新的 ...

  7. martini-拓扑映射

    如何为一个新的分子创建拓扑文件? 这是martini应用的关键.http://jerkwin.github.io/2016/08/31/Martini%E5%B8%B8%E8%A7%81%E9%97% ...

  8. http代理阅读3 发送mem处理

    每次客户端有可读数据触发时,优先检测是否还有数据没有发送,如果有则发送数据,然后在读取client数据 //向后端发送请求的调用过程 //ngx_http_upstream_send_request_ ...

  9. Mysql分区、分表、分库

    1.MySQL分区 一般情况下我们创建的表对应一组存储文件,使用MyISAM存储引擎时是一个.MYI和.MYD文件,使用Innodb存储引擎时是一个.ibd和.frm(表结构)文件. 当数据量较大时( ...

  10. modprobe: FATAL: Module ceph not found解决办法

    问题 有可能你在进行 Ceph 文件系统挂载的时候出现下面的提示: modprobe: FATAL: Module ceph not found. mount.ceph: modprobe faile ...