본문 바로가기
C#(CSharp)/Etc

Single Global Mutex

by swconsulting 2019. 6. 25.

 

I want to make sure this is out there, because it's so hard to get right:

using System.Runtime.InteropServices;   //GuidAttribute
using System.Reflection;                //Assembly
using System.Threading;                 //Mutex
using System.Security.AccessControl;    //MutexAccessRule
using System.Security.Principal;        //SecurityIdentifier

static void Main(string[] args)
{
    // get application GUID as defined in AssemblyInfo.cs
    string appGuid =
        ((GuidAttribute)Assembly.GetExecutingAssembly().
            GetCustomAttributes(typeof(GuidAttribute), false).
                GetValue(0)).Value.ToString();

    // unique id for global mutex - Global prefix means it is global to the machine
    string mutexId = string.Format( "Global\\{{{0}}}", appGuid );

    // Need a place to store a return value in Mutex() constructor call
    bool createdNew;

    // edited by Jeremy Wiebe to add example of setting up security for multi-user usage
    // edited by 'Marc' to work also on localized systems (don't use just "Everyone") 
    var allowEveryoneRule =
        new MutexAccessRule( new SecurityIdentifier( WellKnownSidType.WorldSid
                                                   , null)
                           , MutexRights.FullControl
                           , AccessControlType.Allow
                           );
    var securitySettings = new MutexSecurity();
    securitySettings.AddAccessRule(allowEveryoneRule);

   // edited by MasonGZhwiti to prevent race condition on security settings via VanNguyen
    using (var mutex = new Mutex(false, mutexId, out createdNew, securitySettings))
    {
        // edited by acidzombie24
        var hasHandle = false;
        try
        {
            try
            {
                // note, you may want to time out here instead of waiting forever
                // edited by acidzombie24
                // mutex.WaitOne(Timeout.Infinite, false);
                hasHandle = mutex.WaitOne(5000, false);
                if (hasHandle == false)
                    throw new TimeoutException("Timeout waiting for exclusive access");
            }
            catch (AbandonedMutexException)
            {
                // Log the fact that the mutex was abandoned in another process,
                // it will still get acquired
                hasHandle = true;
            }

            // Perform your work here.
        }
        finally
        {
            // edited by acidzombie24, added if statement
            if(hasHandle)
                mutex.ReleaseMutex();
        }
    }
}
shareimprove this answer
edited Oct 15 '18 at 7:35
community wiki
18 revs, 14 users 31%
Sam Saffron
1
you may want to omit using to check createdNew and add mutex.Dispose() inside finally. I can't explain it clearly (I don't know the reason) right now but I've got myself to a situation when mutex.WaitOne returned true after createdNew became false (I acquired the mutex in the current AppDomain and then loaded a new AppDomain and executed the same code from within it). – Sergey.quixoticaxis.Ivanov Feb 7 '17 at 14:44
1. Does exitContext = false do anything in mutex.WaitOne(5000, false)? It looks like it could only cause an assert in CoreCLR, 2. If anyone's wondering, in Mutex's constructor, the reason why initiallyOwned is false is partially explained by this MSDN article. – jrh Nov 1 '17 at 17:30
2
A tip: watch out using Mutex with ASP.NET: "The Mutex class enforces thread identity, so a mutex can be released only by the thread that acquired it. By contrast, the Semaphore class does not enforce thread identity.". An ASP.NET request can be serviced by multiple threads. – Sam Rueby Nov 14 '17 at 20:58

 

 

 

source : 

https://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in-c/229567

 

What is a good pattern for using a Global Mutex in C#?

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 Regardless of the locale my machine is ...

stackoverflow.com