9

Typically I see these two pieces of code all around. Both works in my case too, but which should I stick to?

Case 1:

bool isNew = false;
Mutex mutex = new Mutex(true, "MyApp_Mutex", out isNew);
if (!isNew)
{
    MessageBox.Show("already running.", "Multiple Instances Not Allowed",
                                        MessageBoxButtons.OK, 
                                        MessageBoxIcon.Exclamation);
    return;
}

Case 2:

Mutex mutex = new Mutex(false, "MyApp_Mutex"))            
if (!mutex.WaitOne(0, false))
{
    MessageBox.Show("already running.", "Multiple Instances Not Allowed", 
                                        MessageBoxButtons.OK, 
                                        MessageBoxIcon.Exclamation);
    return;
}
  1. Which is the ideal way between the two to prevent multiple instances?

  2. What is the difference?

  3. Moreover I see codes like these:

    //if not return{
    mutex.ReleaseMutex(); 
    GC.Collect(); 
    //application.Run();
    GC.KeepAlive(mutex); 
    

under the second method but never with the first. Why is that so? Or did I get that wrong?

Basically it lies with the proper understanding of the parameters and methods used. I would appreciate if someone can briefly detail it, I understand not half when reading msdn documentation..

nawfal
  • 70,104
  • 56
  • 326
  • 368

2 Answers2

8

In the first case, you're asking the OS to create the mutex and give you ownership of it if it's created - this is done through the first parameter, initiallyOwned. The isNew parameter tells you whether or not it was a new mutex. If it's new then you're guaranteed to have ownership of it since that's what you asked for with the initiallyOwned parameter. Since it's new, and you own it, you know there are no other instances of the application running, because if there were, they would have already created the mutex and they would own it.

The second case is basically the same thing, but done in a slightly different way. It's not requesting ownership on the create, but on the WaitOne call. WaitOne is requesting ownership, and waiting for 0 milliseconds. If you get ownership then you know no other instance of your app is running, for the same reasons as case 1.

As for which to use, to my knowledge it doesn't matter. The first seems to be more intuitive, at least to me.

Adding answer to new question #3

When the app is complete it should release the mutex since it owns it. .NET will likely release it for you when your app exits, but it's good practice to do it. GC.Collect and GC.KeepAlive are dealing with garbage collection. I can't think of any scenario why these calls would be needed when dealing with the mutexes controlling startup. I declare my mutex as static, so it will always be in scope and won't be freed by the garbage collector for the lifetime of my app.

Dave Carlile
  • 7,347
  • 1
  • 20
  • 23
  • I've one more doubt which I will add to the question. Will be of great help if you can look into that. – nawfal Aug 24 '11 at 15:51
3

In order to understand what is going on in these statements, one must understand what a mutex is and how they operate. I won't go into any great detail but I will point you to this reference book. Read the first few chapters until you get to the section about Mutexes.

The declaration of the Mutex in your first snippet of code uses the isNew bool to specify that the current application instance was the first to run, as well as the first instance to create the Mutex. This means each secondary execution of your application can be informed that their handle to the system-wide Mutex was not the first one to create and access the Mutex.

The following if block then checks to see if the associated task was the first to signal the Mutex and then handles the state accordingly.

The second snippet of code is completely different. A Mutex can be used in a task (task B) to wait for another task (task A) to signal the Mutex that any other task (task B) can continue.

The WaitOne(secs, releaseConext) method is saying, wait for the Mutex to send a Signal response for X seconds if it is locked by another thread. If the method doesn't get a signal response in X seconds, it returns false and, in the case of your sample code, enters the if block which is used to close the application.

Personally, I would use the first snippet of code. I would imagine that they both operate with the same amount of overhead. However, in choosing which version to use I would consider the first method to be the best one to use as a general matter of practice.

RLH
  • 15,230
  • 22
  • 98
  • 182
  • I've one more doubt which I will add to the question – nawfal Aug 24 '11 at 15:45
  • Sorry, I didn't get to respond to your updated, additional question (#3) before C.C.G. responded. He's nailed the response on the head. Yes, the additional code is considered "good practice" but the GC has been well optimized over the past 10 years and I've never found the need to have such code. +1 to CCG. – RLH Aug 24 '11 at 16:12
  • Yeah it sounds logical to me too, but then, why would it be that no one mentions about GC and all that along with the first approach? – nawfal Aug 24 '11 at 16:14
  • It depends on how old the code is. Especially if you are finding articles, that reference articles, that reference articles... that originated back in the days of .Net 1.1. This type of code was a little more important back then. – RLH Aug 24 '11 at 16:41
  • I would also use a global named mutex, so that your single-instance logic will work in a Terminal Services server environment. – ahazzah Aug 24 '11 at 19:10
  • @ahazzah , I understand that. Its not much important in my case – nawfal Aug 25 '11 at 05:44