Why doesn't Mutex get released when disposed?

后端 未结 9 1170
青春惊慌失措
青春惊慌失措 2020-11-29 02:22

I have the following code:

using (Mutex mut = new Mutex(false, MUTEX_NAME))
{
    if (mut.WaitOne(new TimeSpan(0, 0, 30)))
    {
       // Some code that dea         


        
9条回答
  •  庸人自扰
    2020-11-29 02:43

    The documentation explains (in the "Remarks" section) that there is a conceptual difference between instantiating a Mutex object (which does not, in fact, do anything special as far as synchronization goes) and acquiring a Mutex (using WaitOne). Note that:

    • WaitOne returns a boolean, meaning that acquiring a Mutex can fail (timeout) and both cases must be handled
    • When WaitOne returns true, then the calling thread has acquired the Mutex and must call ReleaseMutex, or else the Mutex will become abandoned
    • When it returns false, then the calling thread must not call ReleaseMutex

    So, there's more to Mutexes than instantiation. As for whether you should use using anyway, let's take a look at what Dispose does (as inherited from WaitHandle):

    protected virtual void Dispose(bool explicitDisposing)
    {
        if (this.safeWaitHandle != null)
        {
            this.safeWaitHandle.Close();
        }
    }
    

    As we can see, the Mutex is not released, but there is some cleanup involved, so sticking with using would be a good approach.

    As to how you should proceed, you can of course use a try/finally block to make sure that, if the Mutex is acquired, that it gets properly released. This is likely the most straightforward approach.

    If you really don't care about the case where the Mutex fails to be acquired (which you haven't indicated, since you pass a TimeSpan to WaitOne), you could wrap Mutex in your own class that implements IDisposable, acquire the Mutex in the constructor (using WaitOne() with no arguments), and release it inside Dispose. Although, I probably wouldn't recommend this, as this would cause your threads to wait indefinitely if something goes wrong, and regardless there are good reasons for explicitly handling both cases when attempting an acquire, as mentioned by @HansPassant.

提交回复
热议问题