概述

前面一篇 About Windows 10 SDK Preview Build 17110 中,我们简单介绍了 Multi-instance UWP Apps,今天结合开发过程详细讲解一下。

在 Windows 10 Version 1803 以前,UWP App 同一时间只能启动一个实例,而在 1803 开始,UWP App 可以通过开发者的配置选择来支持多实例。如果一个多实例 UWP App 正在运行,这时一个激活请求发送过来,平台不会直接激活当前的实例,而是会创建一个新的实例,运行在单独的进程中。

开发过程

配置多实例支持

多实例特性需要在 Visual Studio 中安装新的项目模板:Multi-Instance App Project Templates.VSIX, 安装后,使用 C# 和 C++ 都可以创建项目。

两个模板会被安装:

  • Multi-Instance UWP app -- 创建一个多实例的 App
  • Multi-Instance Redirection UWP app -- 提供一个附加的逻辑,让用户可以选择启动新实例,或者选择目前激活的实例。可以想象一下 Office 打开或编辑文件时的场景。

这两个模板都会在 manifest 文件中添加 SupportsMultipleInstances,其中 desktop4 和 iot2 前缀标志了项目只支持传统桌面 Windows 和 IoT 系统。manifest 配置如下,我们只保留了新增的部分:

<Package
...
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:iot2="http://schemas.microsoft.com/appx/manifest/iot/windows10/2"
IgnorableNamespaces="uap mp desktop4 iot2">
...
<Applications>
<Application Id="App"
...
desktop4:SupportsMultipleInstances="true"
iot2:SupportsMultipleInstances="true">
...
</Application>
</Applications>
...
</Package>

实际运行时,每次点击 App 的磁贴,都会启动一个新的实例。如下图中,App 显示了启动的时间,在任务栏和运行窗口可以看到,两个实例同一时间在运行状态。

多实例激活重定向

UWP App 对多实例的支持,可以让同一 App 的多个实例可以同时在运行。它运行开发者自己定义,是每次开启一个新的实例,还是重定向某个目前激活的应用。举例来说,让你想使用 App 编辑一个文件,而这个文件正在 App 中被编辑,这时就不应该再开启一个新的实例,而是应该重定向当前正在编辑文件的实例。这就会用到 Multi-Instance Redirection UWP app 模板。

Multi-Instance Redirection UWP app 模板和我们上面看到的一样,对 manifest 文件会做同样的调整。同时该模板会增加一个 Program.cs 文件,在文件中包含一个 Main() 方法,靠这个方法来实现多实例激活的重定向操作。

我们来重点看看 Program.cs 文件中的 Main() 方法

  • activatedArgs 中包含了应用启动时我们定义的参数,我们根据这些参数,比如 key 来决定多实例的重定向方式;
  • AppInstance.RecommendedInstance 系统推荐的实例,如果有,我们可以重定向到这个实例;
  • 多实例间唯一性的标识 key 的生成方式,我们可以根据 activatedArgs 来自定义,在默认的示例代码中,采用了随机数判断单双数的方式;
  • FindOrRegisterInstanceForKey(key) 会查询当前对应 key 的实例,如果没有则新注册一个实例;
  • 判断实例是不是新注册的,如果是则启动,如果是查询到的原有实例,则重定向到那个实例;
static void Main(string[] args)
{
// First, we'll get our activation event args, which are typically richer
// than the incoming command-line args. We can use these in our app-defined
// logic for generating the key for this instance.
IActivatedEventArgs activatedArgs = AppInstance.GetActivatedEventArgs(); // In some scenarios, the platform might indicate a recommended instance.
// If so, we can redirect this activation to that instance instead, if we wish.
if (AppInstance.RecommendedInstance != null)
{
AppInstance.RecommendedInstance.RedirectActivationTo();
}
else
{
// Define a key for this instance, based on some app-specific logic.
// If the key is always unique, then the app will never redirect.
// If the key is always non-unique, then the app will always redirect
// to the first instance. In practice, the app should produce a key
// that is sometimes unique and sometimes not, depending on its own needs.
uint number = CryptographicBuffer.GenerateRandomNumber();
string key = (number % == ) ? "even" : "odd";
var instance = AppInstance.FindOrRegisterInstanceForKey(key);
if (instance.IsCurrentInstance)
{
// If we successfully registered this instance, we can now just
// go ahead and do normal XAML initialization.
global::Windows.UI.Xaml.Application.Start((p) => new App());
}
else
{
// Some other instance has registered for this key, so we'll
// redirect this activation to that instance instead.
instance.RedirectActivationTo();
}
}
}

对于 key 的构造和判断,以及判断后的处理,是多实例重定向的关键,我们先看看 FindOrRegisterInstanceForKey(key) 和 IsCurrentInstance 的注释:

//
// 摘要:
// 如果另一个实例已注册该密钥,使用平台注册一个应用实例,或查找现有实例。
//
// 参数:
// key:
// 作为实例密钥的非空字符串。
//
// 返回结果:
// 表示已注册密钥的第一个应用的应用实例。
public static AppInstance FindOrRegisterInstanceForKey(string key); //
// 摘要:
// 应用的当前实例是否是该实例定义的特定密钥的已注册实例。
//
// 返回结果:
// 指示当前应用是否为该应用的已注册实例的布尔值。
public bool IsCurrentInstance { get; }

后台任务和多实例

关于后台任务的多实例,官方有以下说明:

  • 进程外的后台任务支持多实例,通常,每个新触发的结果会独立在一个后台任务的实例中;
  • 进程内的后台任务不支持多实例;
  • 后台音乐任务不支持多实例;
  • 当应用注册一个后台任务时,它通常会首先检查这个任务是否已经注册了,如果已注册,或删除重新创建它,或维持当前的注册。这也是多实例应用的典型特点。然而,多实例应用可能会选择在每个实例的基础上注册一个不同的后台任务名。这对导致多次注册相同的触发器,并且触发器触发时将会激活多个任务实例;
  • 应用服务会为每一个应用服务后台任务的连接启动一个单独的实例,这对多实例应用保持不变,即多实例应用的每个实例都会获得自己的应用服务后台任务实例;

其他注意事项

关于多实例应用,官方文档还提示了一些额外的注意事项:

  • 支持多实例应用的 UWP 应用,只能面向传统桌面系统和 IoT;
  • 为避免竞争条件和资源争夺的问题,多实例应用需要采取措施,分区和同步权限到对访问进行设置,应用本地存储和任何其他资源(如用户文件,数据存储等),以在多个实例间完成共享。标准的同步机制包括 mutexes,semaphores,events 等都是可用的;
  • 如果应用的 Package.appxmanifest 文件中存在 SupportsMultipleInstances 字段,那么他的扩展中不需要再声明 SupportsMultipleInstances;
  • 如果你把 SupportsMultipleInstances 添加到除后台任务,应用服务之外的的任何其他扩展中,并且托管该扩展的应用没有在 Package.appxmanifest 中声明 SupportsMultipleInstances,则会发生模式错误;
  • 应用可以在 manifest 中使用 ResourceGroup 来把多个后台任务分组到同一个宿主中, 这和多实例是冲突的,每个活动都会出现在单独的宿主中。因为一个应用不能同时声明 SupportsMultipleInstances 和 ResourceGroup;

多实例应用的介绍就到这里,大家可以结合自己应用的实际场景,更加合理的设置 key 和判断条件来使用多实例,谢谢!

New Windows 10 SDK - Multi-instance UWP apps的更多相关文章

  1. About Windows 10 SDK Preview Build 17110

    在 Windows Developer Day 活动同时,微软正式 Release 了 Windows 10 SDK Preview Build 17110. Windows 10 SDK Previ ...

  2. New Windows 10 SDK - Toast Notification

    概述 Toast Notification 在 UWP App 中有很重要的作用,能够很大程度上增强 App 和用户之间的沟通,比如运营推广活动.版本更新.提醒类任务提示等等.Toast Notifi ...

  3. Windows 10 SDK 10.0.10069 : The installer failed. User cancelled installation. Error code: -2147023294

    注* 请先跳到文章后面的配置“操作系统的区域设置”部分,然后尝试重试安装VS,如果仍然失败,请看下面内容. 安装UAP SDK失败 Visual Studio 2015 RC Community 安装 ...

  4. 修复Windows 10 SDK 17763中NavigationView上的AcrylicBrush丢失

    原文 修复Windows 10 SDK 17763中NavigationView上的AcrylicBrush丢失 Microsoft发布了新版本的Windows 10 UWP SDK Build 17 ...

  5. Windows 10 SDK 10.0.10158

    昨天微软发布了Windows 10 SDK 10158版本: http://blogs.windows.com/buildingapps/2015/06/30/windows-10-sdk-previ ...

  6. 被 Windows 10 SDK 坑了

    抓包抓到的配置文件与完整版的VS一致,虽然显示出来的只有 Windows 10 通用工具,我还以为是只更新这些(因为列出来的几个,我确实之前没装),就愉快地点了安装,结果……新建项目时,发现 Wind ...

  7. 自动启动 Windows 10 UWP 应用

    原文: https://docs.microsoft.com/zh-cn/windows/uwp/xbox-apps/automate-launching-uwp-apps 简介 开发人员有多种选项可 ...

  8. 打造理想的Windows 10 APP开发环境的5个步骤

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:微软即将发布Windows 10手机版,实际上很多人现在已经开始在开发Windows ...

  9. Windows 10 IoT Serials 10 – 如何使用OCR引擎进行文字识别

    1. 引言 OCR (Optical Character Recognition,光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗.亮的模式确定其形状,然后用字符识别方 ...

随机推荐

  1. Dockerfile 编译安装mysql5.7 千万不要执行.只是记录一下编译安装罢了

    开启所有核心make  20G 内存都不够玩,跑3-4个核心吧,还好. 最后的出来的镜像3G多,百思不得其解,看了官方的Dockerfile,也没什么特别,就是 apt 或者 yum.好吧,不知做了什 ...

  2. 安装apache报没有找到VCRUNTIME40.dll错误

    解决办法 在Windows下运行最新版的Apache和php7都需要Visual C++Redistributable 2015,而之前的版本不需要那么高的,这个组件是运行Visual Studio ...

  3. Hbase的存储

    Hbase在生态系统中的位置 Hbase存储的逻辑视图 Hbase的存储格式 Hbase写数据流程 Hbase快速响应数据 Hbase在生态系统中的位置 HBase位于结构化存储层,Hadoop HD ...

  4. 如何在WDM中使用xp系统的DMA用来处理数据

    最近做了一款pci的视频采集卡(H264压缩),由于数据传输量比较大,所有想采用dma来传输数据,刚开始感觉很简单,后来感觉还是困难重重. DMA 验证监控直接内存访问 (DMA) 的使用.随着 Wi ...

  5. weak alias

    Weak Alias 跟 Weak Reference 完全没有任何关系,不过是我在看到 Weak Reference 的时候想到的而已. Weak Alias 是 gcc 扩展里的东西,实际上是函数 ...

  6. 在Ubuntu 中使用Source Code Pro字体

    1.下载字体 推荐GitHub上面的项目主页上下载 Source Code Pro 2.解压 unzip SourceCodePro_FontsOnly-1.013.zip 3. 打开SourceCo ...

  7. FusionCharts饼图中label值太长怎么解决

    FusionCharts饼图中label值太长怎么解决 1.使用hoverText属性 <?xml version="1.0" encoding="UTF-8&qu ...

  8. List转换成JSON对象报错(三)

    List转换成JSON对象 1.具体错误如下 Exception in thread "main" java.lang.NoClassDefFoundError: net/sf/e ...

  9. solaris启动过程详解

    在Sparc平台下,Solaris系统中有一个类似PC BIOS的芯片程序(EEPROM OpenBoot)负责识别分区.文 件系统和加载内核,在Solaris 2.6之后的版本中,默认的内核文件存放 ...

  10. JavaScript获取select下拉框中的第一个值

    JavaScript获取select下拉框中的第一个值 1.说明 获取select下拉框中的第一个值 2.实现源码 <!DOCTYPE html PUBLIC "-//W3C//DTD ...