为什么不互斥体处置时得到释放? [英] Why doesn't Mutex get released when disposed?
问题描述
我有以下代码:使用
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
returnstrue
, then the calling thread has acquired the Mutex and must callReleaseMutex
, or else the Mutex will become abandoned - When it returns
false
, then the calling thread must not callReleaseMutex
那么,还有比实例更互斥。至于你是否应该使用使用
无论如何,让我们来看看什么的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屋!