1

I am using a Mutex object to prevent multiple instances of the application from running at the same time.

This is the relevant code:

// class attribute
private static Mutex applicationMutex = new Mutex(true, "MyProgram"); 

// Main()
try
{
    if (!applicationMutex.WaitOne(TimeSpan.Zero, true))
    {
        MessageBox.Show("Already running.");
        Application.Current.Shutdown();
    }
}
catch (AbandonedMutexException)
{
    // pass
}

It seems to work fine, but I noticed that sometimes it seems to "hang": for example, if I terminate the program while debugging using the "stop" button in Visual Studio I'm usually unable to relaunch my application unless I disconnect my user and log back in. This morning it even happened after a reboot!

What am I doing wrong?

Michele Ippolito
  • 686
  • 1
  • 5
  • 12
  • I have had similar struggles. Namely if I accidently publish my app in debug mode, update it on my computer, realise the error, publish in production mode and then update it again. The error then happens to me. The Mutex, as far as I have found, is something your Windows session keeps track of and I have not found a way to shut down a "rogue" Mutex - it seems part of the design of the Mutex, so you either make sure to `Release` your Mutex while you own it or you have to log out and back in to Windows. At least that's what I found. – Heki Mar 28 '18 at 07:57
  • Is it not possible to catch the application exit event and release the mutex?, so the program can terminate gracefully. – Thangadurai Mar 28 '18 at 08:06
  • `Mutex` is a primitive used for synchronizing access to code. It's not suitable to synchronize access in a reliable way to the process itself. You need a little reliable util app that will work as 'a man in a middle' and monitor your main application state, terminate it if it's in an unresponsive state. It can check running processes set mutex to signaling state etc... But it MUST be reliable, a windows service could be a good choice. – Fabjan Mar 28 '18 at 08:59
  • https://msdn.microsoft.com/en-us/library/bwe34f1k(v=vs.110).aspx – Hans Passant Mar 28 '18 at 09:37
  • https://msdn.microsoft.com/en-us/library/microsoft.visualbasic.applicationservices.windowsformsapplicationbase.issingleinstance(v=vs.110).aspx – Hans Passant Mar 28 '18 at 09:39

1 Answers1

2

When you create a named Mutex object during debugging, your code is unlikely to call ReleaseMutex() on the acquired mutex - especially when you stop the debugging session from VS.

To address your 'hang' problem directly, you can specify a timeout in your WaitOne call. Otherwise it will wait forever for the mutex to be released, which will never happen as it is abandoned.

While I don't have time to write up a test for it, it seems that an abandoned mutex may possibly be acquired again, see Mutex.OpenExisting. It has not been an issue to us after looking at whether the app is production or not:

If your app is WPF, check if ApplicationDeployment.IsNetworkDeployed and only acquire the mutex in that case. It will be true when the app has been published and installed from that location and obviously false when you are debugging.

Otherwise, use the #if DEBUG Preprocessor Directive to avoid running the mutex code and always debug with the "Debug" configuration and release with the "Release" config. Make sure that the "Define DEBUG constant" is checked for the debug config in the project properties.

Always called ReleaseMutex when your application ends, whether it happens by user action or otherwise. I'm not sure how to go on about this with a console application though, but WPF has a catch much like ASP.NET has in its Global.asax.

I hope this helps.

Heki
  • 926
  • 2
  • 15
  • 34
  • 1
    Regarding your last point, `Mutex` implements `IDisposable` and can be used inside a `using` block to make sure it is always released. – Rotem Mar 28 '18 at 09:14
  • Remember that disposing the mutex object does not release the mutex itself. Refer to [.NET Source: Mutex.cs](https://referencesource.microsoft.com/#mscorlib/system/threading/mutex.cs) and [Why doesn't Mutex get released when disposed?](https://stackoverflow.com/questions/25432596/why-doesnt-mutex-get-released-when-disposed) – Heki Mar 28 '18 at 09:31