默认情况下,Windows 应用 SDK桌面应用可以同时运行多个实例。 每个实例作为单独的进程运行。 您可以使用 Microsoft.Windows.AppLifecycle.AppInstance 类来控制此行为,以注册实例、检测现有实例并重定向激活。
多实例管理场景
- 单实例强制 实施 - 将新激活重定向到已运行的实例。
- 基于密钥的路由 - 将不同的文件或 URI 路由到特定实例(例如,每个文档一个实例)。
- 实例发现 - 枚举所有正在运行的实例以协调工作。
使用密钥注册实例
在您的应用的 Main 方法中使用 AppInstance.FindOrRegisterForKey 来声明一个密钥。 如果密钥已由另一个实例注册,则可以重定向激活。 以下自定义 Main 方法应放在 Program.cs 中,并且位于任何 XAML 初始化之前:
using Microsoft.Windows.AppLifecycle;
public static class Program
{
[STAThread]
static async Task Main(string[] args)
{
// Required before calling any other Windows App SDK or WinRT API
// from a custom entry point.
WinRT.ComWrappersSupport.InitializeComWrappers();
// Determine a key for this activation
string instanceKey = "main-instance";
var activatedArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
if (activatedArgs.Kind == ExtendedActivationKind.File)
{
var fileArgs = activatedArgs.Data as
Windows.ApplicationModel.Activation.IFileActivatedEventArgs;
// Use the file path as the instance key to route
// each file to its own instance
if (fileArgs?.Files is { Count: > 0 })
{
instanceKey = fileArgs.Files[0].Path;
}
}
var instance = AppInstance.FindOrRegisterForKey(instanceKey);
if (!instance.IsCurrent)
{
// Another instance owns this key — redirect activation to it
await instance.RedirectActivationToAsync(activatedArgs);
return; // Exit this process
}
// This instance owns the key — proceed with normal startup
// Register for future redirected activations
instance.Activated += OnActivated;
Application.Start((p) =>
{
var context = new DispatcherQueueSynchronizationContext(
DispatcherQueue.GetForCurrentThread());
SynchronizationContext.SetSynchronizationContext(context);
_ = new App();
});
}
private static void OnActivated(object? sender, AppActivationArguments args)
{
// Handle the redirected activation on the UI thread
// For example, open the file or navigate to the URI
}
// App is the application type generated by the WinUI 3 project template
// (App.xaml / App.xaml.cs).
private partial class App : Microsoft.UI.Xaml.Application
{
}
}
注释
若要使用自定义 Main 方法,请禁用自动生成的入口点。 在 .csproj 中,将 <DefineConstants>$(DefineConstants);DISABLE_XAML_GENERATED_MAIN</DefineConstants> 设置为追加该符号而不覆盖现有定义。
强制实施单实例行为
若要使应用单实例化,请始终使用相同的密钥:
var instance = AppInstance.FindOrRegisterForKey("single-instance");
if (!instance.IsCurrent)
{
await instance.RedirectActivationToAsync(
AppInstance.GetCurrent().GetActivatedEventArgs());
return;
}
列出正在运行的实例
使用 AppInstance.GetInstances() 来发现所有已注册的实例:
var instances = AppInstance.GetInstances();
foreach (var inst in instances)
{
System.Diagnostics.Debug.WriteLine(
$"Key: {inst.Key}, ProcessId: {inst.ProcessId}");
}
取消注册实例
实例关闭时,会自动删除注册。 您还可以显式地取消注册:
AppInstance.GetCurrent().UnregisterKey();
与 UWP 多实例的差异
| 功能 | UWP | Windows 应用 SDK |
|---|---|---|
| 命名空间 | Windows.ApplicationModel.AppInstance |
Microsoft.Windows.AppLifecycle.AppInstance |
| 清单要求 |
SupportsMultipleInstances 属性 |
桌面应用无需此项 |
| 实例发现 | AppInstance.GetInstances() |
AppInstance.GetInstances() (相同模式) |
| 激活重定向 | AppInstance.RedirectActivationTo() |
AppInstance.RedirectActivationToAsync() (异步) |
| 自定义主入口点 | 必需 | 必需(采用相同方式) |