释放在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();
似乎OnExit方法有最好的机会在同一个线程中,但即使这似乎是一个粗略的假设。是否有一种方法可以忽略同一线程的要求?或者我应该创建和存储一个单独的线程与我的互斥锁?

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

我个人根本不会费心发布它,特别是因为你处理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线程是确保这一点的最简单的方法。

相关文章: