释放在WPF Application.OnStartUp()中创建的命名互斥锁:哪个线程拥有它
本文关键字:拥有 线程 OnStartUp Application WPF 创建 释放 | 更新日期: 2023-09-27 18:12:30
我在WPF应用程序的OnStartup
方法中创建了一个互斥锁。该互斥锁不会在程序的其他任何地方使用,其唯一目的是防止某些程序并发运行。如何在应用程序关闭时释放这个互斥锁?
根据文档,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();}
processsexit事件处理程序中的 - ?
AppDomain.CurrentDomain.ProcessExit += (sender,e)=> releaseMutex();
终结器中的 - ?
~App(){releaseMutex();}
- 在未处理的异常事件处理程序?
AppDomain.CurrentDomain.UnhandledException += (sender,e)=> releaseMutex();
我个人根本不会费心发布它,特别是因为你处理AbandonedMutexException
。
如果互斥锁不用于同步同一进程的线程,则不需要显式释放它。当一个进程终止时,操作系统会自动关闭该进程创建的所有句柄,如文件、套接字、互斥锁、信号量和事件句柄。
如果你仍然喜欢释放它,可以考虑使用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线程是确保这一点的最简单的方法。