本主题介绍如何创建多实例通用 Windows 平台 (UWP) 应用。
从 Windows 10 版本 1803(10.0; 构建 17134)开始,您的 UWP 应用可以选择支持多个实例。 如果多实例 UWP 应用的实例正在运行,并且随后的激活请求通过,则平台将不会激活现有实例。 相反,它将创建一个新实例,并在单独的进程中运行。
重要
JavaScript 应用程序支持多实例化,但不支持多实例重定向。 由于 JavaScript 应用程序不支持多实例重定向, 因此 AppInstance 类不适用于此类应用程序。
选取启用多实例功能
如果要创建新的多实例应用程序,可以安装
注释
多实例应用项目模板不再可用。 VSIX 模板是一种方便工具,因此你需要修改现有项目,如下所示。 请务必将 DISABLE_XAML_GENERATED_MAIN 常量添加到项目生成符号中,因为这样可以防止构建时生成默认的 Main()。 这允许使用一个专为应用程序编写的 Main() 版本。
已安装两个模板: 多实例 UWP 应用,该应用提供用于创建多实例应用的模板和 多实例重定向 UWP 应用,该应用提供可构建以启动新实例或有选择地激活已启动的实例的其他逻辑。 例如,你可能一次只想要一个实例编辑同一文档,因此,将该文件打开的实例引入前台,而不是启动新实例。
这两个模板将SupportsMultipleInstances
添加到package.appxmanifest
文件中。 请注意命名空间前缀 desktop4
和 iot2
:仅面向桌面或物联网(IoT)的项目支持多实例化。
<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>
多实例激活重定向
对于 UWP 应用的多实例支持,不仅仅是让应用可以启动多个实例。 若您希望自定义选择是启动应用的新实例还是激活已有的运行实例,该功能允许进行相应设置。 例如,如果启动应用以编辑已在另一个实例中编辑的文件,则可能需要将激活重定向到该实例,而不是打开另一个已编辑该文件的实例。
欲了解多实例 UWP 应用的创建过程,请观看此视频演示。
多实例重定向 UWP 应用 模板将 SupportsMultipleInstances
添加到 package.appxmanifest 文件中,如上所示,还会向您的项目中添加一个包含 函数的 Program.cs 文件(或 Main()
文件,如果您使用的是模板的 C++ 版本)。 用于重定向激活的逻辑应放入Main
函数中。
Program.cs的模板如下所示。
AppInstance.RecommendedInstance 属性表示此激活请求的 shell 提供的首选实例(如果有)(或者null
不存在)。 如果 shell 提供首选项,则可以将激活重定向到该实例,也可以忽略它(如果选择)。
public static class Program
{
// This example code shows how you could implement the required Main method to
// support multi-instance redirection. The minimum requirement is to call
// Application.Start with a new App object. Beyond that, you may delete the
// rest of the example code and replace it with your custom code if you wish.
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();
// If the Windows shell indicates a recommended instance, then
// the app can choose to redirect this activation to that instance instead.
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.
string key = Guid.NewGuid().ToString(); // always unique.
//string key = "Some-App-Defined-Key"; // never unique.
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();
}
}
}
}
Main()
是首先运行的内容。 它在 OnLaunched 和 OnActivated之前运行。 这允许你在应用运行任何其他初始化代码之前确定是激活此实例还是另一个实例。
上面的代码用于确定是激活应用程序的现有实例还是创建并激活一个新实例。 密钥用于确定是否存在要激活的现有实例。 例如,如果应用可以启动以 处理文件激活,则可以将文件名用作密钥。 然后,可以检查应用的实例是否已注册到该密钥并激活它,而不是打开新实例。 这是代码背后的想法: var instance = AppInstance.FindOrRegisterInstanceForKey(key);
如果找到使用密钥注册的实例,则会激活该实例。 如果未找到密钥,则当前实例(当前正在运行 Main
的实例)将创建其应用程序对象并开始运行。
后台任务和多实例化
- 进程外后台任务支持多实例化。 通常,每个新触发器都会导致后台任务的新实例(尽管从技术上讲,多个后台任务可能在同一主机进程中运行)。 不过,会创建后台任务的其他实例。
- 进程内后台任务不支持多实例化。
- 后台音频任务不支持多实例化。
- 当应用注册后台任务时,它通常首先检查任务是否已注册,然后删除并重新注册该任务,或者不执行任何作来保留现有注册。 这仍然是多实例应用的典型行为。 但是,多实例应用可以选择根据每个实例注册不同的后台任务名称。 这将导致对同一触发器的多次注册,当触发器启动时,将激活多个后台任务实例。
- 应用服务为每个连接启动一个独立的应用服务后台任务实例。 对于多实例应用,这保持不变,即多实例应用的每个实例都将获取其自己的应用服务后台任务实例。
其他注意事项
- 面向桌面和物联网(IoT)项目的 UWP 应用支持多实例化。
- 为了避免竞争条件和争用问题,多实例应用需要采取措施来分区/同步对设置、应用本地存储以及任何其他资源(如用户文件、数据存储等)的访问,这些资源可供多个实例共享。 可以使用标准同步机制,例如标准互斥锁、标准信号量、标准事件等。
- 如果应用在其 Package.appxmanifest 文件中包含
SupportsMultipleInstances
,则其扩展无需声明SupportsMultipleInstances
。 - 如果将
SupportsMultipleInstances
添加到任何其他扩展,除了后台任务或应用服务,而承载该扩展的应用没有在其 Package.appxmanifest 文件中声明SupportsMultipleInstances
,则会生成架构错误。 - 应用可以使用清单中的 ResourceGroup 声明将多个后台任务分组到同一主机中。 这与多实例相冲突,因为每次激活都会进入不同的主机。 因此,应用程序无法在其清单中同时声明
SupportsMultipleInstances
和ResourceGroup
。
示例
有关多实例激活重定向的示例,请参阅 多实例示例。
另请参阅
AppInstance.FindOrRegisterInstanceForKeyAppInstance.GetActivatedEventArgsAppInstance.RedirectActivationTo处理应用激活