Releasing a named mutex created in WPF Application.OnStartUp(): Which thread owns it?

纵饮孤独 提交于 2019-12-24 05:22:09

问题


I create a mutex within the OnStartup Method of a WPF app. The mutex is not used anywhere else in the program, its only purpose is to prevent certain programs from running concurrently. How can I release this mutex when the application closes?

According to the documentation, mutex.ReleaseMutex() must be called from the same thread that created the mutex. However this presents a problem, since I do not control the thread that calls OnStartup().

Suppose my OnStartup method looks like this:

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();
        }
    }
}

Is it save to call releaseMutex() ...

  • in the OnExit() method?
    protected override void OnExit(){releaseMutex();}
  • in the ProcessExit event handler?
    AppDomain.CurrentDomain.ProcessExit += (sender,e)=> releaseMutex();
  • in a finalizer?
    ~App(){releaseMutex();}
  • in the unhandled exception event handler?
    AppDomain.CurrentDomain.UnhandledException += (sender,e)=> releaseMutex();

It seems like the OnExit method has the best chance to be in the same thread, but even that seems a sketchy assumption. Is there a way to ignore the same-thread requirement? Or should I create and store a separate thread in conjunction with my mutex?


回答1:


I personally wouldn't bother releasing it at all, especially since you handle AbandonedMutexException.

If a mutex is not used to synchronize threads of the same process there is no need to explicitly release it. When a process terminates OS automatically closes all handles created by the process, such as files, sockets, mutexes, semaphores and event handles .

If you still prefer to release it consider using Application.OnExit() since it is called from the main thread, just like the Startup().




回答2:


According to my research, every GUI WPF application has a UI thread which can be accessed via Application.Current.Dispatcher (see for example this answer). This UI thread should always remain active for the lifetime of the application.

You can use Dispatcher.CheckAccess to see whether you are running in the UI thread, and if you are not you can use Dispatcher.Invoke to execute an action in the context of the UI thread.

The description of Application.Run implies that Application.OnStartup is always run on the UI thread, but it should not be harmful to check and, if necessary, use the UI thread dispatcher to invoke the action that creates the mutex.

It seems a reasonable guess that Application.OnExit is also always run on the UI thread, but since this does not appear to be documented, you should check and, if necessary, use the UI thread dispatcher to invoke the action that releases the mutex.

As Alexm correctly points out, you do not in fact need to explicitly release the mutex provided that the application is running in its own process (which will usually be the case) but you do need to ensure that the thread the mutex is created on will remain active until you are ready to free it. I believe using the UI thread is the simplest way to ensure this.



来源:https://stackoverflow.com/questions/32535686/releasing-a-named-mutex-created-in-wpf-application-onstartup-which-thread-own

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!