【问题标题】:C# Mutex always stuck on WaitOneC# Mutex 总是卡在 WaitOne 上
【发布时间】:2017-08-01 14:59:01
【问题描述】:

我有一个进程创建互斥体并立即获得所有权,然后当单击一个按钮时,它会释放它:

Mutex req_mutex = new Mutex(true, "req_mutex");

...

req_mutex.WaitOne(); // not required for first click
req_mutex.ReleaseMutex();

另一个进程正在循环并检查互斥体是否存在,当它存在时等待它被释放:

bool waitingForReqMutexCreation = true;
while (waitingForReqMutexCreation)
{
      try
      {
           req_mutex = Mutex.OpenExisting("req_mutex", MutexRights.Synchronize);
           waitingForReqMutexCreation = false;
      }
      catch (WaitHandleCannotBeOpenedException)
      {
           Thread.Sleep(1000);
      }
}

...

req_mutex.WaitOne(); // wait for new request   *********** problem here *********
req_mem.readFile(); // read request
req_mutex.ReleaseMutex(); // release req mutex for more requests

问题在于,即使在第一个进程中的按钮应该释放互斥锁之后,WaitOne 也不会继续。

有人知道为什么会这样吗?

【问题讨论】:

    标签: c# mutex


    【解决方案1】:

    我认为如果您使用 true (new Mutex(true, "req_mutex");) 创建互斥锁 所以在这个过程中你不需要打电话给WaitOne()

    文档说在调用此构造函数重载时最好为 initialOwned 指定 false。 https://msdn.microsoft.com/en-us/library/f55ddskf(v=vs.110).aspx

    编辑:啊,你打败了我 :) ...

    【讨论】:

      【解决方案2】:

      您基本上在第一个应用程序中获得了两次互斥锁。您可以通过在第二个应用程序运行时杀死您的第一个应用程序来看到这一点,您将获得一个AbandonedMutexException(这意味着 Mutex 被获取)。使用以下 readline 而不是按钮单击进行复制:

      namespace Mutex_1
      {
          class Program
          {
              static void Main(string[] args)
              {
                  Mutex req_mutex = new Mutex(true, "req_mutex");
      
                  String t = string.Empty;
      
                  while (!t.Contains("q"))
                  {
                      Console.WriteLine("input: ");
                      t = Console.ReadLine();
      
                      Console.WriteLine("waiting for req_mutex");
                      req_mutex.WaitOne(); // not required for first click
                      Console.WriteLine("releasing req_mutex");
                      req_mutex.ReleaseMutex();
                  }
      
                  Console.ReadLine();
              }
          }
      }
      
      namespace Mutex_2
      {
          class Program
          {
              static void Main(string[] args)
              {
                  Mutex req_mutex = null;
      
                  bool waitingForReqMutexCreation = true;
                  while (waitingForReqMutexCreation)
                  {
                      try
                      {
                          req_mutex = Mutex.OpenExisting("req_mutex");
                          waitingForReqMutexCreation = false;
                      }
                      catch (WaitHandleCannotBeOpenedException)
                      {
                          Console.WriteLine("req_mutex does not exist.");
                          Thread.Sleep(1000);
                      }
                  }
                  Console.WriteLine("req_mutex found");
                  req_mutex.WaitOne(); // wait for new request   *********** problem here *********
                  Console.WriteLine("after req_mutex.WaitOne()");
                  req_mutex.ReleaseMutex(); // release req mutex for more requests
      
                  Console.ReadLine();
              }
          }
      }
      

      更多证据支持此声明:在父级中调用ReleaseMutex 两次将使事情在第一次“点击”时工作(并在第二次崩溃)。您可以通过在创建锁时不获取锁来解决此问题而不会引发异常:

      Mutex req_mutex = new Mutex(false, "req_mutex");
      

      【讨论】:

        【解决方案3】:

        我想我找到了自己问题的答案...

        显然,您执行的 WaitOne 操作的数量确实很重要。 我取得了所有权(构造函数中的真实参数)并在同一个线程中做了一个额外的 WaitOne 假设它不会受到伤害。 现在为了释放互斥锁,我显然不得不调用 ReleaseMutex 两次。

        我想我仍然可以这样做并在循环中调用 ReleaseMutex 直到抛出异常......

        【讨论】:

        • 永远不要循环调用 ReleaseMutex。如果您无法准确知道应该释放互斥锁的次数,那么您的应用程序设计不佳。在您的情况下,正如其他人指出的那样,互斥锁最初不应该是自己的。或者,您应该在初始化完成后释放它。 无论如何,你现在应该做你正在做的事情。 多线程不是你可以猜测的东西。如果您做错了,您的应用程序将无法始终按预期工作。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-11
        • 1970-01-01
        • 2019-03-31
        • 2013-12-29
        • 2013-01-11
        相关资源
        最近更新 更多