Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: How to prevent two instances of an application from doing the same thing at the same time?

If you have two threads within an application, and you don't want them to run a certain piece of code simultaneously, you can just put a lock around the piece of code, like this:

lock (someObject) {
    // ... some code
}

But how do you do the same thing across separate processes? I thought this is what you use a "global mutex" for, so I tried the Mutex class in various ways, but it doesn't seem to fulfill my requirements, which are:

  • If you're the only instance, go ahead and run the code.
  • If you're the second instance, wait for the first one to finish, then run the code.
  • Don't throw exceptions.

Problems I ran into:

  • Just instantiating a Mutex object in a using(){...} clause doesn't seem to do anything; the two instances still happily run concurrently
  • Calling .WaitOne() on the Mutex causes the first instance to run and the second to wait, but the second waits indefinitely, even after the first calls .ReleaseMutex() and leaves the using(){} scope.
  • .WaitOne() throws an exception when the first process exits (System.Threading.AbandonedMutexException).

How do I solve this? Solutions that don't involve Mutex are very welcome, especially since Mutex appears to be Windows-specific.

like image 476
Timwi Avatar asked Feb 24 '10 21:02

Timwi


1 Answers

I have two applications:

ConsoleApplication1.cs

using System;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Mutex mutex = new Mutex(false, "AwesomeMutex");

            Console.WriteLine("ConsoleApplication1 created mutex, waiting . . .");

            mutex.WaitOne();

            Console.Write("Waiting for input. . .");
            Console.ReadKey(true);

            mutex.ReleaseMutex();
            Console.WriteLine("Disposed mutex");
        }
    }
}

ConsoleApplication2.cs

using System;
using System.Threading;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Mutex mutex = new Mutex(false, "AwesomeMutex");
            Console.WriteLine("ConsoleApplication2 Created mutex");

            mutex.WaitOne();

            Console.WriteLine("ConsoleApplication2 got signalled");

            mutex.ReleaseMutex();
        }
    }
}

Starting ConsoleApplication1, followed by ConsoleAplication2 works perfectly with no errors. If your code still bombs out, its a bug with your code, not the Mutex class.

like image 173
Juliet Avatar answered Oct 06 '22 11:10

Juliet