【问题标题】:Mutex already acquired even though no instance is running即使没有实例正在运行,也已获取互斥锁
【发布时间】:2018-03-28 07:50:37
【问题描述】:

我正在使用Mutex 对象来防止应用程序的多个实例同时运行。

这是相关代码:

// class attribute
private static Mutex applicationMutex = new Mutex(true, "MyProgram"); 

// Main()
try
{
    if (!applicationMutex.WaitOne(TimeSpan.Zero, true))
    {
        MessageBox.Show("Already running.");
        Application.Current.Shutdown();
    }
}
catch (AbandonedMutexException)
{
    // pass
}

它似乎工作正常,但我注意到有时它似乎“挂起”:例如,如果我在调试时使用 Visual Studio 中的“停止”按钮终止程序,我通常无法重新启动我的应用程序,除非我断开了我的用户并重新登录。今天早上它甚至在重新启动后发生了!

我做错了什么?

【问题讨论】:

  • 我也有过类似的挣扎。也就是说,如果我不小心在调试模式下发布了我的应用程序,在我的计算机上更新它,发现错误,在生产模式下发布,然后再次更新。然后错误发生在我身上。据我所知,Mutex 是你的 Windows 会话跟踪的东西,我还没有找到关闭“流氓”Mutex 的方法——它似乎是 Mutex 设计的一部分,所以你要么确保Release 您拥有 Mutex 或您必须注销并重新登录 Windows。至少这是我发现的。
  • 难道不能捕获应用退出事件并释放互斥锁吗?这样程序就可以优雅地终止了。
  • Mutex 是用于同步访问代码的原语。不适合以可靠的方式将访问同步到进程本身。您需要一个可靠的 util 应用程序,它可以作为“中间人”工作并监控您的主应用程序状态,如果它处于无响应状态则终止它。它可以检查正在运行的进程,将互斥锁设置为信号状态等...但它必须可靠,Windows 服务可能是一个不错的选择。

标签: c# .net mutex


【解决方案1】:

当您在调试期间创建一个命名为 Mutex 的对象时,您的代码不太可能在获取的互斥锁上调用 ReleaseMutex() - 特别是当您从 VS 停止调试会话时。

要直接解决您的“挂起”问题,您可以在您的WaitOne 电话中specify a timeout。否则它将永远等待互斥锁被释放,这将永远不会发生,因为它被放弃了。

虽然我没有时间为它编写测试,但似乎可能会再次获得废弃的互斥锁,请参阅Mutex.OpenExisting。在查看应用程序是否生产后,这对我们来说不是问题:

如果您的应用程序是 WPF,请检查 ApplicationDeployment.IsNetworkDeployed 并仅在这种情况下获取互斥锁。当应用程序已从该位置发布和安装时,它将是 true,而在您调试时显然是错误的。

否则,请使用#if DEBUG Preprocessor Directive 避免运行互斥代码并始终使用“调试”配置进行调试并使用“发布”配置进行发布。确保在项目属性中检查调试配置的“定义调试常量”。

在您的应用程序结束时始终调用ReleaseMutex,无论它是由用户操作还是其他方式发生。虽然我不确定如何使用控制台应用程序来解决这个问题,但 WPF 的功能很像 ASP.NET 在其Global.asax 中的功能。

我希望这会有所帮助。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-05
  • 2021-07-05
  • 2012-12-25
  • 2011-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多