This is the sixth part of the Concurrency series. For your convenience you can find other parts in the table of contents in Part 1 – Mutex performance in .NET
Let’s start with the following code:
static void Main(string args)
var mutex = new Mutex(false, "mutexName");
We want to acquire a mutex. Since the operation might fail, we want to log the timeout, handle the exception and try again. Finally, we want to release the mutex, catch all exceptions and then exit.
Start this application three times: first instance should acquire the mutex, second and third should just wait. Now kill forcibly first instance (i.e., using Process Explorer). Now one of two other instances should acquire the mutex. Let’s say, that it was the second instance. Focus it and hit enter. It should say
Mutex released and wait on another
Console.ReadLine(). We expect the third instance to acquire the mutex, however, it still shows timeouts. Why is that?
You could use Chain Traversal API to figure out what is happening. However, everything is as designed. If you consult the documentation, you will see the following exception:
The wait completed because a thread exited without releasing a mutex. This exception is not thrown on Windows 98 or Windows Millennium Edition.
What is not stated explicitly is: when you get this exception, the mutex IS acquired. This means that our first catch just swallows the exception of an operation which actually succeeded. We loop again, acquire the mutex again (since it is recursive). Later when we release it, it is still locked because we miss one more release.
Solution? Whenever you get this exception you need to break the loop because the mutex is acquired.