The Mutex class is very misunderstood, and Global mutexes even more so.
What is good, safe pattern to use when creating Global mutexes?
One that will work
Using the accepted answer I create a helper class so you could use it in a similar way you would use the Lock statement. Just thought I'd share.
Use:
using (new SingleGlobalInstance(1000)) //1000ms timeout on global lock
{
//Only 1 of these runs at a time
RunSomeStuff();
}
And the helper class:
class SingleGlobalInstance : IDisposable
{
//edit by user "jitbit" - renamed private fields to "_"
public bool _hasHandle = false;
Mutex _mutex;
private void InitMutex()
{
string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value;
string mutexId = string.Format("Global\\{{{0}}}", appGuid);
_mutex = new Mutex(false, mutexId);
var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
var securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryoneRule);
_mutex.SetAccessControl(securitySettings);
}
public SingleGlobalInstance(int timeOut)
{
InitMutex();
try
{
if(timeOut < 0)
_hasHandle = _mutex.WaitOne(Timeout.Infinite, false);
else
_hasHandle = _mutex.WaitOne(timeOut, false);
if (_hasHandle == false)
throw new TimeoutException("Timeout waiting for exclusive access on SingleInstance");
}
catch (AbandonedMutexException)
{
_hasHandle = true;
}
}
public void Dispose()
{
if (_mutex != null)
{
if (_hasHandle)
_mutex.ReleaseMutex();
_mutex.Close();
}
}
}
Sometimes learning by example helps the most. Run this console application in three different console windows. You'll see that the application you ran first acquires the mutex first, while the other two are waiting their turn. Then press enter in the first application, you'll see that application 2 now continues running by acquiring the mutex, however application 3 is waiting its turn. After you press enter in application 2 you'll see that application 3 continues. This illustrates the concept of a mutex protecting a section of code to be executed only by one thread (in this case a process) like writing to a file as an example.
using System;
using System.Threading;
namespace MutexExample
{
class Program
{
static Mutex m = new Mutex(false, "myMutex");//create a new NAMED mutex, DO NOT OWN IT
static void Main(string[] args)
{
Console.WriteLine("Waiting to acquire Mutex");
m.WaitOne(); //ask to own the mutex, you'll be queued until it is released
Console.WriteLine("Mutex acquired.\nPress enter to release Mutex");
Console.ReadLine();
m.ReleaseMutex();//release the mutex so other processes can use it
}
}
}