zoukankan      html  css  js  c++  java
  • 2020年的UWP(4)——UWP和等待Request的Desktop Extension

    上一篇我们讨论了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等方法。

        public class AppServiceConnectionConnectedEventArgs : EventArgs
        {
            public AppServiceConnection Connection { get; }
    
            public AppServiceConnectionConnectedEventArgs(AppServiceConnection connection)
            {
                Connection = connection;
            }
        }
    
       public event EventHandler<AppServiceConnectionConnectedEventArgs> Connected;

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

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

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

            private async void ButtonLaunchApp_Click(object sender, RoutedEventArgs e)
            {
                if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
                {
                    AppServiceHandler.Instance.Connected += Instance_Connected;
                    await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
                }
            }
    
            private async void Instance_Connected(object sender, AppServiceConnectionConnectedEventArgs e)
            {
                AppServiceHandler.Instance.Connected -= Instance_Connected;
                var valueSet = new ValueSet();
                valueSet.Add("FileName", ComboBoxFileName.SelectionBoxItem);
                var response = await e.Connection.SendMessageAsync(valueSet);
            }

    之所以需要这个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给注释掉了。

            public async Task InitializeAsync()
            {
                Connection = new AppServiceConnection();
                Connection.PackageFamilyName = Package.Current.Id.FamilyName;
                Connection.AppServiceName = "ParameterAppService";
                AppServiceConnectionStatus status = await Connection.OpenAsync();
                if (status != AppServiceConnectionStatus.Success)
                {
                    Console.WriteLine(status);
                }
                else
                {
                    Console.WriteLine(status);
                    Connection.RequestReceived += Connection_RequestReceived;
                }
            }
    
            private void Connection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
            {
                var content = args.Request.Message["FileName"].ToString();
                Process.Start(content);
                Console.WriteLine("Will exit after received.");
                //Environment.Exit(0);
            }

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

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

  • 相关阅读:
    剑指offer4:重建二叉树(后序遍历)
    剑指offer3:从尾到头打印链表每个节点的值
    剑指offer2:C++实现的替换空格(字符中的空格替换为“%20”)
    tp5系统变量输出(可以用来传递搜索的参数)
    Ajax实现文件上传的临时垃圾文件回收策略
    php获取当天的开始时间和结束时间
    Think PHP递归获取所有的子分类的ID (删除当前及子分类)
    tp查找某字段,排除某字段,不用一次写那么多
    git-查看历史版本及回滚版本
    dedecms目录结构,非常全
  • 原文地址:https://www.cnblogs.com/manupstairs/p/14065673.html
Copyright © 2011-2022 走看看