【问题标题】:How can I get rid of an abandoned mutex?如何摆脱废弃的互斥锁?
【发布时间】:2014-10-21 17:01:20
【问题描述】:

总结:

如果创建互斥锁的进程已经死掉了,有没有办法清除它?

详情:

我使用互斥锁来确保我的应用程序只有一个实例运行。

在测试一些新代码(进行自动更新)时,我运行了 Environment.Exit(0)。在调试模式下运行时,我的互斥体被清理得很好。

但是当我将构建更改为“发布”时,互斥锁会在退出调用后保留并被标记为已放弃:

我已仔细检查以确保没有任何进程仍在运行该互斥锁所附加到的进程。

现在每次我运行我的应用程序时,它都认为互斥锁仍然存在并且不会启动我的应用程序。 (它也会崩溃,因为它试图向应用程序的“当前运行”实例发送消息以显示自己。)

我试图像这样释放互斥锁:

bool createdNew;
string applicationId = "18773:TestStudio";
var singleInstanceMutex = new Mutex(true, applicationId, out createdNew);

singleInstanceMutex.Close();  // Tried ReleaseMutex() too

当然,这只是获取它然后释放它。

我知道我可以重新启动,但我希望得到更好的修复,以防在生产中发生这种情况。

如果创建互斥锁的进程已经死掉了,有没有办法清除它?

【问题讨论】:

  • 根据您的屏幕截图,3 件事仍在引用它。关闭任何 3 件仍然有句柄的东西。
  • @Scott Chamberlain - 参考仍然存在,但过程早已不复存在。它以一种没有释放引用的方式死亡。因此我的问题是如何释放互斥锁。
  • @Vccano 那么你有两种情况之一。一个损坏的操作系统安装,或者一些你没有意识到引用的东西正在引用。如果它真的消失了,那么计数将为 0,在 Windows 95(或 98,我不记得是哪个)中修复了来自失败进程的句柄清理。可能的情况是程序还没有真正死掉,当你认为它已经死时,有些东西仍然让它活着,或者其他一些程序(IIS,一种防病毒软件,谁知道)正在拿起句柄而不放手。
  • 您是否尝试过更改您的程序以按照我的代码的方式执行操作,看看是否可以避免问题发生?

标签: c# .net mutex


【解决方案1】:

不知道这是否真的回答了你的问题,但这是我用于此目的的代码:

  // Mutex object used to determine if there are multiple instances of this program running. 
  //  Note that this is a reference to a .Net Mutex object, not the Windows mutex itself.
  private static Mutex _onlyOneInstanceMutex;



  /// <summary>
  /// Method to test that there is not another instance of the program already running on this 
  /// machine, or at least in this Terminal Services session or Windows Vista / Windows 7 
  /// concurrent sessions session. If there is, a message box-style localized error message is 
  /// displayed and the value false is returned. This implies that this method should not be 
  /// used in programs that are run as a Windows service.
  /// 
  /// This implementation uses a .Net Mutex object in public storage to prevent it from being 
  /// garbage-collected. The name of the associated Windows mutex is simply the program name as 
  /// provided by the caller. Neither the .Net Mutex object nor the Windows mutex are ever 
  /// explicitly released; they remain in existence, perhaps in an "abandoned" state, until the 
  /// process that created them terminates.
  /// </summary>
  /// <returns>false if another instance running, otherwise true</returns>
  [SuppressMessage("Microsoft.Reliability", "CA2004:RemoveCallsToGCKeepAlive",
                   Justification = "Not sure if this is correct or not.")]
  public static bool TestOnlyOneInstance(string programName)
  {
     // Funny construct to prevent the Mutex from being garbage collected
     GC.KeepAlive(_onlyOneInstanceMutex);

     // Test if we are the first instance, and if so create the Windows mutex, making it 
     //  impossible for subsequent instances to successfully create their mutex
     bool firstInstance;
     _onlyOneInstanceMutex = new Mutex(false, programName, out firstInstance);
     if (firstInstance)
        return true;

     // Display a (possibly localized) error message, then return
     string errorMessage = MLocalizer.GetString("Error1", 
           "Another instance of this program is already running on this machine.") +
         "\n" + MLocalizer.GetString("Error2",
                                     "You cannot run two instances at the same time.") +
         "\n" + MLocalizer.GetString("Error3", "Please use the other instance.");
     MessageBox.Show(errorMessage, programName, MessageBoxButtons.OK, MessageBoxIcon.Error);
     return false;
  }

编辑:

我在我的代码和你的代码中可以看到的唯一区别是我将“最初拥有”指定为 false,而且我对垃圾收集有一个有趣的事情。

哦,我将 Mutex 声明为静态的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 2012-06-05
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    • 2021-05-06
    相关资源
    最近更新 更多