WPF 单实例应用示例

配套文章:WPF 单实例应用:Mutex 仲裁与命名管道通信。

需要 Windows 与 .NET 10 SDK,无第三方包依赖。示例的业务窗口只展示参数,不打开文件或执行收到的命令。

运行窗口

在本目录执行:

dotnet build SingleInstanceDemo.csproj
./bin/Debug/net10.0-windows/SingleInstanceDemo.exe "首次请求.txt"

保留窗口,再从终端启动同一个程序:

./bin/Debug/net10.0-windows/SingleInstanceDemo.exe "含 空格的文件.txt" --example

窗口应显示同一个主实例 PID 和第二次请求。可以先最小化、最大化后再最小化,观察恢复行为。系统可能拒绝前台激活,示例会尝试提示任务栏,不保证每次取得焦点。

应用身份固定为 Example.SingleInstanceDemo.v1,Mutex 限于同一用户、同一登录会话。示例按相同提升级别通信;管道两端的 CurrentUserOnly 在 Windows 上也检查提升级别。换用产品自己的稳定身份时,应明确不同版本是否共享同一个主实例。

文件

验证

运行:

dotnet run --project Tests/SingleInstanceTests.csproj
./VerifyArticle.ps1

16 项检查覆盖:并发进程仲裁、其他句柄存活时接管、异常退出接管、重复取得资格、稳定身份、参数与目录往返、并发请求、启动缓冲、发送前重试、确认丢失、队列满、畸形消息、空闲客户端、两个停止阶段和过大请求。

并发仲裁使用 6 个独立子进程和启动/释放信号,保证它们的竞争时间重叠。异常退出场景只在测试子进程中使用 Environment.Exit,不影响用户的其他进程。测试失败时回收自己启动的子进程,正常验证不显示窗口或调用前台激活 API。

VerifyArticle.ps1 检查文章关键代码与项目源文件一致、目录锚点和围栏完整,然后编译 WPF 项目。它不等同于完整 Jekyll 构建。

窗口恢复、任务栏提示、多用户、跨会话和混合提升权限由人工在相应环境验证;自动检查只覆盖列出的仲裁与通信行为。

交付与退出约定

accepted 只表示请求进入内存队列。客户端发送后未收到匹配的确认,返回 Uncertain,不会自动重发或创建第二个业务窗口。请求编号用来关联确认,没有跨进程重启的持久去重功能。

服务器使用 64 KiB 帧上限、32 条等待请求的队列、2 秒连接交换期限;入口尝试连接和重新仲裁的总期限约为 5 秒。返回 NotSent 的失败可以在期限内重试,明确拒绝和结果不确定都结束本次启动。

窗口关闭时,示例取消监听和未执行的 UI 调度,等待收尾完成后再由入口线程释放 Mutex。窗口关闭前已经入队但未处理的请求可能丢失,需要排空或持久化的产品应实现自己的关闭协议。