我在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()
...
protected override void OnExit(){releaseMutex();}
AppDomain.CurrentDomain.ProcessExit += (sender,e)=> releaseMutex();
~App(){releaseMutex();}
AppDomain.CurrentDomain.UnhandledException += (sender,e)=> releaseMutex();
似乎OnExit方法有最好的机会在同一个线程中,但即使这似乎是一个粗略的假设。有没有办法忽略相同的线程要求?或者我应该与我的互斥锁一起创建和存储一个单独的线程吗?
答案 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线程是确保这一点的最简单方法。