C# Mutex 总是卡在 WaitOne 上

C# Mutex always stuck on WaitOne

我有一个创建互斥量并立即取得所有权的进程,然后在单击按钮时释放它:

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 也没有继续。

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

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

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

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

我想如果你用 true 创建互斥量 (new Mutex(true, "req_mutex");) 你不需要在那个过程中调用 WaitOne()

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

编辑:啊,你抢先了我 :) ...

您基本上是在第一个应用程序中获取了两次互斥量。您可以通过在第二个应用程序为 运行 时终止第一个应用程序来看到这一点,您将获得一个 AbandonedMutexException(这意味着获得了 Mutex)。使用以下内容转载,而不是单击按钮:

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 两次将使事情在第一次 "click" 上运行(并在第二次崩溃)。您可以通过在创建锁时不获取锁来解决此问题而不会引发异常:

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