Often, you’ll want to prevent users from starting more than one instance of an application at a time. This could be to avoid confusion, avoid data loss or may be it doesn’t make sense to run more than a single instance at a time. Whatever be the reason, it is easy to do this in C#. As far as I know, there are 2 popular approaches that programmers use these days : the process table approach and the named Mutex approach. The process table approach is slow, error-prone and it requires more lines of code when compared to the other. We discuss the named Mutex approach here.
Mutex
A Mutex is one of the many synchronization constructs available in C#. Mutexes are mutually exclusive objects – one and only one thread can acquire it at a time. The Mutex is different from the familiar Monitor object in that its scope could be system-wide. This means that a Mutex created in one running application can be accessed by another application provided the Mutex is a named Mutex and that it is not acquired by the first application. This allows inter-process synchronization of threads. In C#, the Mutex is represented by the System.Threading.Mutex class. Following are four most commonly used constructors to create a Mutex :
public Mutex()
public Mutex(Boolean initiallyOwned)
public Mutex(Boolean initiallyOwned, String name)
public Mutex(Boolean initiallyOwned, String name, out Boolean whatHappened)
The first constructor simply creates a Mutex which is not initially owned.
The second version of the constructor requires a Boolean argument that indicates whether the calling thread should have initial ownership of the Mutex. If initiallyOwned is true, the calling thread will own the Mutex. If initiallyOwned is false, the Mutex is unowned.
The third version is more interesting – it allows you to name the Mutex. It’s this name that we use to access the Mutex from another process.
The fourth version adds another Boolean argument – whatHappened – to the third version. This out (uninitialized) argument will tell you if your request to own the Mutex was granted or not. If whatHappened is true, your request was honored and that the calling thread was granted the ownership of the Mutex. If whatHappened is false, it indicates that someone else is holding the Mutex now. It is this information that we use to determine if another instance of the application is running or not.
There’s yet another version of the constructor that allows you to specify the access control security to be applied to the named Mutex. It is not discussed here. Let’s jump to the program now :
using System;
using System.Threading;
using System.Windows.Forms;
namespace OnlyOne
{
class OneAndOnlyOne
{
static String _mutexID = "a8b65a4f-9ffb-46fd-a432-bdd3338c423e";
static void Main(string[] args)
{
Boolean _isNotRunning;
using (Mutex _mutex = new Mutex(true, _mutexID, out _isNotRunning))
{
if (_isNotRunning)
{
MessageBox.Show("This is the first instance.");
Console.WriteLine("Press any key to continue...");
Console.Read();
}
else
{
MessageBox.Show("An instance is already running.");
return;
}
}
}
}
}
As you can see, a named Mutex is in action here. The name of the Mutex should be unique enough to avoid any interference with other Mutex objects in other applications running on your system. We pass in an out parameter to the constructor which we will later use to determine the outcome of our request to own the Mutex. Here, if the Mutex is already acquired by some other thread in another instance of the application, this request will be rejected and the value of _isNotRunning will be false. So, we simply return after showing an error message. On the other hand, if the calling thread manages to acquire the Mutex, _isNotRunning will be true. In this case, we know that this is the one and only running instance of this application and we continue as usual.
There are few things to keep in mind from the above program. First, as we mentioned already, make sure that the name of the Mutex is unique. Using a GUID is one way to do it. You can also use the assembly name qualified by the namespace if it is unique enough to distinguish it from others. The second thing to notice is the scope of the Mutex. Consider the below code fragment from a Windows Forms Application :
using System;
using System.Windows.Forms;
using System.Threading;
namespace OneAndOnlyOne
{
static class Program
{
static String _mutexID = "a8b65a4f-9ffb-46fd-a432-bdd3338c423e";
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Boolean _isNotRunning;
Mutex _mutex = new Mutex(true, _mutexID, out _isNotRunning);
if (_isNotRunning)
{
Application.Run(new Form1());
}
else
{
MessageBox.Show("An instance is already running.");
return;
}
}
}
}
Do you see any problem here? Well, don’t worry if you don’t because the problem is not quite obvious. Consider a scenario where this program has been running for a while. Since the Mutex is not used after the form starts running, the garbage collector is free to wipe it out of memory. At this point, we can easily start another instance of the application because the new instance can create a new Mutex with the same old name. One way to prevent this is to tell the GC to keep the Mutex alive as long as the application runs. In code, we call the GC.KeepAlive(Object obj) method. The purpose of the KeepAlive method is to ensure the existence of a reference to an object that is at risk of being prematurely reclaimed by the garbage collector. With the additional call to GC, the code now looks like this :
using System;
using System.Windows.Forms;
using System.Threading;
namespace OneAndOnlyOne
{
static class Program
{
static String _mutexID = "a8b65a4f-9ffb-46fd-a432-bdd3338c423e";
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Boolean _isNotRunning;
Mutex _mutex = new Mutex(true, _mutexID, out _isNotRunning);
if (_isNotRunning)
{
Application.Run(new Form1());
GC.KeepAlive(_mutex);
}
else
{
MessageBox.Show("An instance is already running.");
return;
}
}
}
}
Since Mutex derives from WaitHandle and WaitHandle implements IDisposable, a better approach would be to define the scope of the Mutex using the ‘using’ construct available in C#. This will avoid the extra call to GC and dispose the Mutex properly when finished as shown below :
using System;
using System.Windows.Forms;
using System.Threading;
namespace OneAndOnlyOne
{
static class Program
{
static String _mutexID = "a8b65a4f-9ffb-46fd-a432-bdd3338c423e";
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Boolean _isNotRunning;
using (Mutex _mutex = new Mutex(true, _mutexID, out _isNotRunning))
{
if (_isNotRunning)
{
Application.Run(new Form1());
}
else
{
MessageBox.Show("An instance is already running.");
return;
}
}
}
}
}