Thursday, December 19, 2013

Cross process locking using a named mutex in C#

I needed to have some code be protected that only one process can execute it at a given time across processes. To do this I have used a featured called named mutexes in C# and .NET 4.5 (however you can do this in earlier versions. To make the code nice I wrote some little helpers as seen there

    public class CrossProcessLockFactory
    {
        private static int DefaultTimoutInMinutes = 2;
        public static IDisposable CreateCrossProcessLock()
        {
            return new ProcessLock(TimeSpan.FromMinutes(DefaultTimoutInMinutes));
        }

        public static IDisposable CreateCrossProcessLock(TimeSpan timespan)
        {
            return new ProcessLock(timespan);
        }
    }

    public class ProcessLock : IDisposable
    {
        // the name of the global mutex;
        private const string MutexName = "FAA9569-7DFE-4D6D-874D-19123FB16CBC-8739827-[SystemSpecicString]";

        private Mutex _globalMutex;

        private bool _owned = false;
        

        public ProcessLock(TimeSpan timeToWait)
        {
            try
            {
                _globalMutex = new Mutex(true, MutexName, out _owned);
                if (_owned == false)
                {
                    // did not get the mutex, wait for it.
                    _owned = _globalMutex.WaitOne(timeToWait);
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.Message);
                throw;
            }
        }

        public void Dispose()
        {
            if (_owned)
            {
                _globalMutex.ReleaseMutex();
            }            
            _globalMutex = null;
        }
    }

client code would look something like this:

    class Program
    {
        static void Main(string[] args)
        {
            using (CrossProcessLockFactory.CreateCrossProcessLock())
            {
                // if we get out it is ready
                Console.WriteLine("Using the mutex on process 1. Press any key to release the mutex");
                Console.ReadLine();
            }
        }
    }

This code can be improved to change the mutex name and the timespan from the client code. However for my needs this did the trick.

Update...

It is possible that a process that is holding a lock and owning the mutex dies. In this case the waiting process throws an exception of type AbandonedMutexException . It is a good idea to catch this exception, the process that catches this exception automatically owns the mutex now...

3 comments:

C Sharpens said...

Want to learn C# from basics & in most professional Code development style. I'll have you writing real working applications in no time flat-before you reach the end of course.
Hire C# Teacher.

Manjay said...

I am using your code. But when multiple applications calling this method only one thread is getting this lock and others are always in waiting state. I want it to be shared equally between threads.

Manjay said...
This comment has been removed by the author.