0

I have a .net 3.5 / c# / wpf app that I don't want users to be able to run multiple instances of. So I use the following in my app.xaml.cs

protected override void OnStartup(StartupEventArgs e)
{
    const string mutexName = "Local\\MyApp.SingleInstance";
    try
    {
        // Create a new mutex object with a unique name
        _mutex = new Mutex(false, mutexName);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace +
                    "\n\n" + "Application Exiting…", "Exception thrown");
        Current.Shutdown();
    }

    if (_mutex.WaitOne(0, false))
    {
        base.OnStartup(e);
    }
    else
    {
        MessageBox.Show("app is already open", "Error", MessageBoxButton.OK, MessageBoxImage.Information);
        Current.Shutdown();
    }
    //...show mainwindow or load app
}

My problem is that some of my users report this exception: Exception: The wait completed due to an abandoned mutex. Type: System.Threading.AbandonedMutexException

I can't reproduce this locally, so it's hard for me to figure out what is happening.

Would adding

finally
{
    _mutex.ReleaseMutex();
}

After my try/catch possibly help?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
danSiebes
  • 374
  • 1
  • 12

1 Answers1

0

How about using:

using (var mutex = new Mutex(false, mutexName))
{
    if (mutex.WaitOne(0, false))
    {
        base.OnStartup(e);
    }
    else
    {
        MessageBox.Show("app is already open", "Error", MessageBoxButton.OK, MessageBoxImage.Information);
        Current.Shutdown();
    }
}
John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • 1
    Thank you for the answer! For my own understanding, is the idea: if I use the using statement, the mutex object will be disposed of properly and I don't need to worry about calling .ReleaseMutex? – danSiebes Apr 26 '13 at 01:14
  • Yes, that's it exactly. In general, if it implements `IDisposable`, then put it into a `using` block. That's a simplification, of course, but nearly true. – John Saunders Apr 26 '13 at 01:25
  • -1 Completely wrong. You must release the mutex, and you must release it on the same thread that called `WaitOne`; `Dispose` does *not* do that. You should indeed use a using block, but immediately inside the `WaitOne` success block, `try...finally` should be set up with `ReleaseMutex` called in the `finally` block. See [Why doesn't Mutex get released when disposed?](https://stackoverflow.com/questions/25432596/why-doesnt-mutex-get-released-when-disposed) – jnm2 Dec 30 '15 at 13:53
  • @jnm2 - I'll take your word for it. I'll delete my answer. – John Saunders Dec 30 '15 at 15:45