13

I am trying to use a mutex for the first time and have the following code executing on two separate instances of the program

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();
            }
        }
    }

When I run this, one of the instances (the one i run first) prints

I got the mutex
sleeping
awaking and releasing mutex

The other instance prints

First check - some one locked the mutex

and as soon as the first instance leases the mutex, it crashes at the second wait statement with the exception

The wait completed due to an abandoned mutex.

Any ideas on why I am getting this exception and how i can prevent it ?

Solution: I probably should have read the mdsn documentation more clearly. Thanks Andrew for pointing me in the right direction

You can use the WaitHandle.WaitOne method to request ownership of a mutex. The thread that owns a mutex can request the same mutex in repeated calls to WaitOne without blocking its execution. However, the thread must call the ReleaseMutex method the same number of times to release ownership of the mutex. The Mutex class enforces thread identity, so a mutex can be released only by the thread that acquired it.

nighthawk457
  • 1,102
  • 3
  • 12
  • 27

2 Answers2

19

Your problem is you hold the Mutex twice, but only release it once, due to how you have mis-arranged your if statements. Your first execution catches it twice - in both of those if statements, yet your code only releases it once.

You need to re-organize the ifs so you only capture the mutex one time.

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();
}
Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
-2

I think your problem is stemming from the using (var mutex = new Mutex(false, "mySpecialMutex")) line. When the first thread terminates, it would dispose of the mutex object which, I believe, could cause the error you're getting.

If possible, it would be better to declare the mutex as a (static) class variable outside of that method. Then you would manually instantiate it before starting your threads and dispose of it after they're complete.

David Kirby
  • 98
  • 1
  • 8
  • This is not correct. Named mutexes are system-wide. It is the disposal without releasing it that is causing it to have an error instead of never releasingz though. – Andrew Barber May 10 '12 at 18:14
  • I tried making the variable static and having the threads not terminate but I ended up with the same exception. – nighthawk457 May 10 '12 at 18:16