2013-04-26 50 views
0

我有一个.net 3.5/c#/ wpf应用程序,我不希望用户能够运行多个实例。所以,我用我的app.xaml.cs以下单个实例应用程序AbandonedMutexException

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 
} 

我的问题是,我的一些用户的报告这一异常: 例外:等待完成因放弃的互斥体。 类型:System.Threading.AbandonedMutexException

我不能在本地重现这个,所以我很难找出发生了什么。

会增加

finally 
{ 
    _mutex.ReleaseMutex(); 
} 

后,我的try/catch可能帮助?

+1

你绝对应该有一个'试... finally'。请参阅http://stackoverflow.com/q/635640/56778,尤其是问题中的第二个代码示例。 – 2013-04-26 01:15:01

+0

谢谢,非常有帮助。这有助于解释约翰的答案。 – danSiebes 2013-04-26 01:28:10

+0

另外,要明确的是,'ReleaseMutex'应该只在应用程序关闭时调用。 – jnm2 2015-12-30 14:04:40

回答

0

如何使用:

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(); 
    } 
} 
+1

谢谢你的回答!出于我自己的理解,是这样的想法:如果我使用using语句,互斥对象将被正确处置,我不需要担心调用.ReleaseMutex? – danSiebes 2013-04-26 01:14:36

+0

是的,就是这样。一般来说,如果它实现了'IDisposable',那么把它放到一个'using'块中。这当然是一种简化,但几乎是事实。 – 2013-04-26 01:25:07

+0

-1完全错误。您必须释放互斥锁,并且必须在调用'WaitOne'的同一线程上释放它; '处置'不*做*。你应该确实使用using块,但是立即在'WaitOne'成功块内,'try ... finally'应该使用'finally'块中的'ReleaseMutex'来设置。请参阅[为什么Mutex在处置时不会被释放?](https://stackoverflow.com/questions/25432596/why-doesnt-mutex-get-released-when-disposed) – jnm2 2015-12-30 13:53:46