为什么不互斥体处置时得到释放? [英] Why doesn't Mutex get released when disposed?

查看:203
本文介绍了为什么不互斥体处置时得到释放?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:使用

using (Mutex mut = new Mutex(false, MUTEX_NAME))
{
    if (mut.WaitOne(new TimeSpan(0, 0, 30)))
    {
       // Some code that deals with a specific TCP port
       // Don't want this to run at the same time in another process
    }
}



我已经设置,如果块中的断点,和Visual Studio的另一个实例中运行相同的代码。正如所料, .WaitOne 通话块。然而,令我惊讶的,只要我的继续的初审和使用块终止,我在关于第二个进程得到一个异常。一个废弃的互斥

I've set a breakpoint within the if block, and ran the same code within another instance of Visual Studio. As expected, the .WaitOne call blocks. However, to my surprise, as soon as I continue in the first instance and the using block terminates, I get an exception in the second process about an abandoned Mutex.

解决方法是调用 ReleaseMutex

using (Mutex mut = new Mutex(false, MUTEX_NAME))
{
    if (mut.WaitOne(new TimeSpan(0, 0, 30)))
    {
       // Some code that deals with a specific TCP port
       // Don't want this to run twice in multiple processes
    }

    mut.ReleaseMutex();
}

现在,事情正常工作。

我的问题:通常点一个的IDisposable 是它的清理的你把任何状态的东西,我可以看到也许有多个的等待的和的发布的一个使用块中,但是当句柄互斥配置,不应该得到它自动释放?换句话说,为什么我需要调用 ReleaseMutex 如果我在使用阻止?

My Question: Usually the point of an IDisposable is it cleans up whatever state you put things in. I could see perhaps having multiple waits and releases within a using block, but when the handle to the Mutex is disposed, shouldn't it get released automatically? In other words, why do I need to call ReleaseMutex if I'm in a using block?

我现在也担心,如果如果块崩溃中的代码,我已经放弃了互斥躺在附近。

I'm also now concerned that if the code within the if block crashes, I'll have abandoned mutexes lying around.

有没有把互斥中的任何利益而使用块?或者,我应该只是新达的一个互斥实例,包装在一个try / catch,并调用 ReleaseMutex() 中的最后的块(基本实施正是我的认为的Dispose()会做)

Is there any benefit to putting Mutex in a using block? Or, should I just new up a Mutex instance, wrap it in a try/catch, and call ReleaseMutex() within the finally block (Basically implementing exactly what I thought Dispose() would do)

推荐答案

解释(中文档备注一节),有实例化互斥对象之间的概念上的差异(它的不是的,其实做任何事情就特别为同步云)和获得互斥(使用的 的WaitOne )。需要注意的是:

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 返回一个布尔值,这意味着获取互斥锁可失败的(超时)和这两种情况下必须处理

  • 的WaitOne 收益,然后调用线程已经获取互斥和的必须的通话 ReleaseMutex ,否则互斥锁将被放弃

  • 当它返回,然后调用线程的不得的通话 ReleaseMutex

  • 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

那么,还有比实例更互斥。至于你是否应该使用使用无论如何,让我们来看看什么的Dispose 做(按的inherited从的WaitHandle ):

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.

如果您的真正的不关心那里的互斥不能被收购的情况下(你没有指明,因为你传递一个时间跨度的WaitOne ),你可以换互斥在自己的类实现的IDisposable ,获得互斥体在构造函数(使用 WaitOne的()不带任何参数),然后将其释放在的Dispose 。虽然,我可能不会推荐这一点,因为这会导致你的线程无限期地等待,如果出现错误,也不管有很好的理由企图获取一个明确时,处理这两种情况下,由@HansPassant提及。

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.

这篇关于为什么不互斥体处置时得到释放?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆