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