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

我在WPF应用程序的OnStartup方法中创build一个互斥体。 该程序中没有使用互斥锁,它的唯一目的是防止某些程序同时运行。 如何在应用程序closures时释放此互斥锁?

根据文档 , mutex.ReleaseMutex()必须从创build互斥体的同一线程调用。 然而,这提出了一个问题,因为我不控制调用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();}
  • 在未处理的exception事件处理程序中?
    AppDomain.CurrentDomain.UnhandledException += (sender,e)=> releaseMutex();

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

Solutions Collecting From Web of "释放在WPF中创build的命名互斥体Application.OnStartUp():哪个线程拥有它?"

我个人不会打扰释放它,特别是因为你处理AbandonedMutexException

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

如果你仍然喜欢释放它,考虑使用Application.OnExit()因为它是从主线程调用,就像Startup()

根据我的研究,每个GUI WPF应用程序都有一个可通过Application.Current.Dispatcher访问的UI线程(请参阅此答案 )。 此UI线程应始终在应用程序的生命周期中保持活动状态。

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

Application.Run的描述意味着Application.OnStartup总是在UI线程上运行,但是它不应该对检查有害,并且如果有必要的话,可以使用UI线程分派器来调用创建互斥体的动作。

这似乎是一个合理的猜测, Application.OnExit也总是在UI线程上运行,但由于这似乎没有记录,所以应该检查并在必要时使用UI线程调度程序来调用释放互斥量的操作。

正如Alexm正确地指出的那样,事实上你并不需要明确地释放互斥体,只要应用程序在自己的进程中运行(通常情况就是这样),但是你确实需要确保互斥体创建的线程将会保持活动直到你准备好释放它。 我相信使用UI线程是确保这一点的最简单的方法。