释放在WPF Application.OnStartUp()中创建的命名互斥锁:哪个线程拥有它?

时间:2015-09-12 05:58:09

标签: c# wpf windows multithreading mutex

我在WPF应用的OnStartup方法中创建了一个互斥锁。互斥体不用于程序中的任何其他位置,其唯一目的是防止某些程序同时运行。如何在应用程序关闭时释放此互斥锁?

根据documentation,必须从创建互斥锁的同一线程中调用mutex.ReleaseMutex()。但是这会出现问题,因为我不控制调用OnStartup()的线程。

假设我的OnStartup方法如下所示:

public partial class App : Application
{
    private Mutex mutex;
    private bool hasHandle = false;

    protected override void OnStartup(StartupEventArgs e)
    {
        bool createdNew;
        mutex = new Mutex(false, @"Global\XYZ", out createdNew);
        try
        {
             hasHandle = mutex.WaitOne(5000, false);
             if (!hasHandle)
                 {/*do stuff*/};
        }
        catch (AbandonedMutexException)
        {
             hasHandle = true;
             // do stuff
        }
        base.OnStartup(e);
    }

    private void releaseMutex()
    {
        if (mutex!=null)
        {
             if (hasHandle) mutex.ReleaseMutex();
             mutex.Dispose();
        }
    }
}

保存以致电releaseMutex() ...

    OnExit()方法中的

  • protected override void OnExit(){releaseMutex();}
  • ProcessExit事件处理程序中的

  • AppDomain.CurrentDomain.ProcessExit += (sender,e)=> releaseMutex();
  • 在终结者中?
    ~App(){releaseMutex();}
  • 在未处理的异常事件处理程序中?
    AppDomain.CurrentDomain.UnhandledException += (sender,e)=> releaseMutex();

似乎OnExit方法有最好的机会在同一个线程中,但即使这似乎是一个粗略的假设。有没有办法忽略相同的线程要求?或者我应该与我的互斥锁一起创建和存储一个单独的线程吗?

2 个答案:

答案 0 :(得分:2)

我个人根本不会放弃它,特别是在你处理Application.OnExit()之后。

如果未使用互斥锁同步同一进程的线程,则无需显式释放它。当进程终止时,OS会自动关闭进程创建的所有句柄,例如文件,套接字,互斥锁,信号量和事件句柄。

如果您仍然希望发布它,请考虑使用Startup(),因为它是从主线程调用的,就像WPF一样。

答案 1 :(得分:1)

根据我的研究,每个GUI WPF应用程序都有一个UI线程,可以通过Application.Current.Dispatcher访问(参见例如this answer)。此UI线程应始终在应用程序的生命周期内保持活动状态。

您可以使用Dispatcher.CheckAccess查看您是否在UI线程中运行,如果不是,则可以使用Dispatcher.Invoke在UI线程的上下文中执行操作。

description of Application.Run意味着Application.OnStartup始终在UI线程上运行,但它不应该对检查有害,并且如果需要,使用UI线程调度程序来调用创建互斥锁的操作

似乎可以合理地猜测Application.OnExit也始终在UI线程上运行,但由于这似乎没有记录,您应该检查并在必要时使用UI线程调度程序来调用该操作释放互斥锁。

正如Alexm正确指出的那样,如果应用程序在自己的进程中运行(通常就是这种情况),实际上并不需要显式释放互斥锁,但是你确实需要确保互斥锁的线程是创建后将保持活动状态,直到您准备释放它为止。我相信使用UI线程是确保这一点的最简单方法。