被弃用的互斥锁异常。

13

我第一次尝试使用互斥锁,以下代码在程序的两个独立实例上执行

public void asynchronousCode()
    {
        using (var mutex = new Mutex(false, "mySpecialMutex"))
        {
            if (!mutex.WaitOne(1000, false))
            {
                Console.WriteLine("First check - some one locked the mutex");
            }

            if (!mutex.WaitOne(3000, false))
            {
                Console.WriteLine("Second check- some one locked the mutex");
            }
            else
            {
                Console.WriteLine("I got the mutex");
                Console.WriteLine("sleeping");
                Thread.Sleep(3000);
                Console.WriteLine("Awaking and Releasing mutex");
                mutex.ReleaseMutex();
            }
        }
    }

当我运行这段代码时,其中一个实例(我首先运行的那个)会打印出:

I got the mutex
sleeping
awaking and releasing mutex
另一个实例打印
First check - some one locked the mutex

当第一个程序实例释放互斥锁时,它在第二个等待语句处崩溃并抛出异常。

The wait completed due to an abandoned mutex.

有什么想法可以解决我遇到的异常问题,以及如何防止它发生?

解决方案:我可能应该更仔细地阅读MSDN文档。感谢安德鲁指引我找对了方向。

您可以使用WaitHandle.WaitOne方法请求对互斥体的所有权。拥有互斥体的线程可以在多次调用WaitOne时请求相同的互斥体而不会阻止其执行。但是,线程必须调用ReleaseMutex方法相同次数才能释放对互斥体的所有权。Mutex类强制线程标识,因此只有获取互斥体的线程才能释放它。


2
你的第一次运行两次持有互斥锁,但只释放了一次。因此它放弃了该锁。 - Andrew Barber
2个回答

19

你的问题是你两次持有互斥锁,但只释放了一次,这是由于你错误地排列了 if 语句。你的第一个执行在这两个 if 语句中都捕获了它,但是你的代码只释放了一次。

你需要重新组织 if 语句,以便只捕获一次互斥锁。

bool captured = true;
if (!mutex.WaitOne(1000, false))
{
        Console.WriteLine("First check - some one locked the mutex");
        captured = false;
}
if (!captured && !mutex.WaitOne(3000, false))
{
        Console.WriteLine("Second check- some one locked the mutex");
        captured = false;
}
if (captured)
{
        Console.WriteLine("I got the mutex");
        Console.WriteLine("sleeping");
        Thread.Sleep(3000);
        Console.WriteLine("Awaking and Releasing mutex");
        mutex.ReleaseMutex();
}

-2

我认为你的问题源于 using (var mutex = new Mutex(false, "mySpecialMutex")) 这一行。当第一个线程终止时,它会处理互斥对象,这可能导致你遇到的错误。

如果可能的话,最好将互斥体声明为该方法之外的(静态)类变量。然后,在启动线程之前手动实例化它,并在完成后处理它。


这不正确。命名互斥量是系统范围的。问题在于没有释放而进行处理,导致出现错误,而不是从未释放。 - Andrew Barber
我尝试将变量设为静态并使线程不终止,但最终仍然出现了相同的异常。 - nighthawk457

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接