Regarding WaitOne() method of Mutex Type

Nivedita picture Nivedita · Feb 14, 2013 · Viewed 7.1k times · Source

I have written a small piece of code. something like below

    public static void SetLicence1()
    {
            Console.WriteLine("Setting Aspose Licence in Thread1 ");
            Console.WriteLine(SetAsposeLicense());
    }

    public static void SetLicence2()
    {
        Console.WriteLine("Setting Aspose Licence in Thread2 ");
        Console.WriteLine(SetAsposeLicense());
    }

    public static bool SetAsposeLicense()
    {
        try
        {
            //Declare Mutex variable:            
            using (Mutex mutex = new System.Threading.Mutex(false, "Test"))
            {
                    mutex.WaitOne(TimeSpan.FromSeconds(5));
                    var objLic = new License();
                    objLic.SetLicense(@"C:\Nivedita\License\Aspose.Cells.lic");
                    mutex.ReleaseMutex();
            }
            return true;
        }
        catch(Exception ex)
        {
               Console.WriteLine(ex.StackTrace);               
               return false;
        }
    }       
}

public class TestClass
{
    public static void Main()
    {
        Thread tid1 = new Thread(new ThreadStart(ThreadClass.SetLicence1));
        Thread tid2 = new Thread(new ThreadStart(ThreadClass.SetLicence2));

        tid1.Start();
        tid2.Start();

        Console.Read();
    }
}

This piece of code is working perfectly fine. But here my question is that is there any chance for the WaitOne() method can gets stuck in or across the processes and the mutex object doesnt get released? Although I have used mutex.ReleaseMutex().

Answer

Andrew Savinykh picture Andrew Savinykh · Feb 15, 2013

First of all it's not quite clear what your intention is. If you just want to make sure that the licence can't be set simultaneously by two threads, you need something like this:

static object s_lock = new object();

public static bool SetAsposeLicense()
{
    try
    {
        lock (s_lock)
        {
            var objLic = new License();
            objLic.SetLicense(@"C:\Nivedita\License\Aspose.Cells.lic");

        }
        return true;
    }
    catch(Exception ex)
    {
           Console.WriteLine(ex.StackTrace);               
           return false;
    }
}       

You notice that there is not 5 seconds timeout here. If you want to wait for 5 seconds and set the license regardless if the other thread has finished (basically what your code in the question does), instead of messing with mutex, you better do this (but I have a hard time understanding, why would you want this):

private static object s_lock = new object();

public static bool SetAsposeLicense()
{
    if (Monitor.TryEnter(s_lock, TimeSpan.FromSeconds(5)))
    {
        try 
        {
            return SetLicenseInternal(); 
        }
        finally 
        {
            Monitor.Exit(s_lock);
        }
    }
    return SetLicenseInternal(); 
}

public static bool SetLicenseInternal()
{
    try
    {
        var objLic = new License();
        objLic.SetLicense(@"C:\Nivedita\License\Aspose.Cells.lic");
        return true;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.StackTrace);
        return false;
    }
}

Using the Monitor object is more "native" approach than using mutex and it fits more here, since you don't need cross-process.

As far as Mutex go, it's a wrapper against system Mutex object surfaced to .NET. Named Mutexes are system-wide and visible across process. When you create a .NET Mutex object and supply a name, if the system Mutex with this name does not exist, it's created and wrapped into the .NET object that you get. If the system Mutex with this name was already created before, then this existing Mutex gets wrapped and returned as your new .NET Mutex object.

I don't think that you should use Mutexes in your scenario.