上一篇我们提到了怎么在Desktop Extension中等待并处理UWP端发出的request。在本篇中将描述UWP和Desktop Extension双向交互的场景,即存在从两端各自发出request,交由对方接受处理。
依然是回顾下之前总结的四个场景分类:

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

这种存在多个request/response周期的场景,具有以下特征:

  1. UWP和Desktop Extension两端双向通讯
  2. 通过request传递参数
  3. Desktop Extension端存在用户交互
  4. Desktop Extension端满足条件时退出

该场景示意图如下:

上图仅显示了最简化的双向交互流程,在Sample工程中,以互相发文字消息的UWP和WPF窗体举例。两个窗体始终保持在前台,也不存在AppServiceConnection被销毁的问题。

而实际的业务场景中,可能存在复杂的变化。即特征中提到的“Desktop Extension端满足条件时退出“这一点。

上图展示了Sample工程运行时的界面。如何使用Desktop Extension,及建立AppServiceConnection之前的随笔已解释过,此处不再提及。仅对本篇的不同之处进行分析。
TwoWayExchange.FrontUWP工程是一个简单的UWP工程,在MainPage.cs的构造函数中我们通过AppServiceHandler这个帮助类来注册Connected事件。

        public MainPage()
{
this.InitializeComponent(); if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
{
AppServiceHandler.Instance.Connected += Instance_Connected;
FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
}
}

该事件会在App.xaml.cs中的OnBackgroundActived方法中被触发。这也是我们的代码,实际和AppServiceConnection建立关联的起点。

        protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
base.OnBackgroundActivated(args);
if (args.TaskInstance.TriggerDetails is AppServiceTriggerDetails details)
{
if (details.CallerPackageFamilyName == Package.Current.Id.FamilyName)
{
var deferral = args.TaskInstance.GetDeferral();
args.TaskInstance.Canceled += (sender, e) => { deferral?.Complete(); };
AppServiceHandler.Instance.OnBackgroundActivated(details);
}
}
}

在触发Connected事件后,我们在获得的AppServiceConnection对象上注册RequestReceived事件,同时保存AppServiceConnection对象以供SendMessage时使用。

        private void Instance_Connected(object sender, AppServiceConnectionConnectedEventArgs e)
{
AppServiceHandler.Instance.Connected -= Instance_Connected;
Connection = e.Connection;
Connection.RequestReceived += Connection_RequestReceived;
} private async void Connection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
var message = args.Request.Message;
if (message.TryGetValue("Desktop", out object content))
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{ this.textBoxReceive.Text += $"{content}\n"; });
}
} private async void Button_Click(object sender, RoutedEventArgs e)
{
var valueSet = new ValueSet();
valueSet.Add("UWP", this.textBoxSend.Text);
var response = await Connection.SendMessageAsync(valueSet);
}

而在Desktop Extension的WPF工程中,几乎是对称的代码结构,不同之处无非AppServiceConnection源头是在Desktop端通过OpenAsync方法建立。

        public async Task InitializeAsync()
{
Connection = new AppServiceConnection();
Connection.PackageFamilyName = Package.Current.Id.FamilyName;
Connection.AppServiceName = "TwoWayExchangeAppService";
AppServiceConnectionStatus status = await Connection.OpenAsync();
if (status == AppServiceConnectionStatus.Success)
{
Connection.RequestReceived += Connection_RequestReceived;
}
} private void Connection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
if (args.Request.Message.TryGetValue("UWP", out object content))
{
Dispatcher.Invoke(() => { this.textBoxReceive.Text += $"{content}\n"; });
}
} private async void Button_Click(object sender, RoutedEventArgs e)
{
var message = new ValueSet();
message.Add("Desktop", this.textBoxSend.Text);
await Connection.SendMessageAsync(message);
}

至于用于打包的Packaging工程,创建及注意事项,和前一篇完全一致,不再赘述。
本篇的重点在于双向交互,所以在Desktop端注意Windows.mind和System.Runtime.WindowsRuntime两个文件的引用添加,否则是无法利用AppServiceConnection来通讯的。
虽然本篇给出的示例极为简单,似没有实用价值。而在实际开发中,多有遇到UWP端暂时无法实现的UI及功能,诸如不规则的,透明的,或需要锚定的窗体,Windows桌面右下角的Systray等。均可以通过文中提及的方式来实现交互。
Github:
https://github.com/manupstairs/UWPSamples/tree/master/UWPSamples/DataExchangeUWP/TwoWayExchange

2020年的UWP(5)——UWP和Desktop Extension的双向交互的更多相关文章

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

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

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

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

  3. 2020年的UWP(4)——UWP和等待Request的Desktop Extension

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

  4. 迁移桌面程序到MS Store(9)——APPX With Desktop Extension

    在<迁移桌面程序到MS Store(8)——通过APPX下载Win32Component>中我们讨论了通过APPX来下载Service部分的安装包.但是纯UWP的客户端并不能自动运行下载的 ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 面试题59 - II. 队列的最大值

    请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value.push_back 和 pop_front 的时间复杂度都是O(1). 若队列为空,pop_front 和 ...

  2. idea中快速将类中的属性转为Json字符串的插件

    当我们想要测试接口的时候,难免会根据一个类,一个一个的写json数据,当属性比较少时还行,但当属性多的时候就比较麻烦了, 为了解决这个问题,我们可以安装第三方的插件来快速生成json字符串. 步骤如下 ...

  3. python定时执行详解

    知识点 1. sched模块,准确的说,它是一个调度(延时处理机制),每次想要定时执行某任务都必须写入一个调度. (1)生成调度器:s = sched.scheduler(time.time,time ...

  4. E. Number of Simple Paths 题解(思维)

    题目链接 题目大意 给你n个点(\(\sum n<=2e5\)),n条边,求有多少条路径 题目思路 要明白任意两点的路径只能是1条或者2条 先topo找环(双向边也是可以找的) 然后把环上的每个 ...

  5. 精尽MyBatis源码分析 - 文章导读

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  6. 蚂蚁上市员工人均一套大 House,阿里程序员身价和这匹配吗?

    作者 | 硬核云顶宫 责编 | 伍杏玲 出品 | CSDN(ID:CSDNnews) 上周,蚂蚁集团迎来IPO,其发行价格将达到68.8元,总市值将突破2万亿元.市场对蚂蚁的成长性有着充分的信心,为了 ...

  7. 可变长形参,增强for语句

    `package 可变长形参; public class VarArgumen { public static int max(int...varArgs) {//就有可变长形参的求最大值方法 //可 ...

  8. Oracle11gR2 RAC voting disk error

    故障现象:2+3节点配置,alert日志中提示vote盘错误,集群无法拉起来. 分析过程:Oracle 11g RAC依据OLR,OCR,VOTE磁盘进行节点信息注册,维护集群状态以及完成选举投票.其 ...

  9. 在Mac下配置JDK

    1.下载JDK,例JDK8U144 下载地址https://pan.baidu.com/s/1upjecBzTIMnyz0JmdkYprQ 2.安装 安装后配置JDK环境变量 cd ~ open .b ...

  10. Prometheus 使用之 node exporter

    本文使用的 Prometheus 版本为 2.22.0,node exporter 版本为 1.0.1:部署在 Linux 服务器Prometheus 是开源的监控报警系统和时序列数据库 (TSDB) ...