处置时为什么Mutex不会被释放?

时间:2022-04-14 09:44:05

I have the following code:

我有以下代码:

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
    }
}

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.

我在if块中设置了一个断点,并在另一个Visual Studio实例中运行相同的代码。正如所料,.WaitOne调用阻止。然而,令我惊讶的是,一旦我继续第一个实例并且使用块终止,我在第二个过程中得到一个关于被遗弃的互斥锁的例外。

The fix is to call ReleaseMutex:

修复是调用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();
}

Now, things work as expected.

现在,事情按预期工作。

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?

我的问题:通常IDisposable的意思是它清理你放入的任何状态。我可以看到在使用块中可能有多个等待和释放,但是当处理Mutex的句柄时,它不应该被释放自动?换句话说,如果我在使用块中,为什么需要调用ReleaseMutex?

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

我现在也担心如果if块中的代码崩溃了,我会放弃躺在那里的互斥锁。

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)

将Mutex放入使用块有什么好处吗?或者,我应该只是新建一个Mutex实例,将它包装在try / catch中,并在finally块中调用ReleaseMutex()(基本上实现了我认为Dispose()会做的事情)

9 个解决方案

#1


49  

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 returns a boolean, meaning that acquiring a Mutex can fail (timeout) and both cases must be handled
  • WaitOne返回一个布尔值,这意味着获取互斥锁可能会失败(超时),并且必须处理这两种情况
  • When WaitOne returns true, then the calling thread has acquired the Mutex and must call ReleaseMutex, or else the Mutex will become abandoned
  • 当WaitOne返回true时,调用线程已获取Mutex并且必须调用ReleaseMutex,否则Mutex将被放弃
  • When it returns false, then the calling thread must not call ReleaseMutex
  • 当它返回false时,调用线程不能调用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):

因此,Mutexes比实例化更多。至于你是否应该继续使用,让我们来看看Dispose的作用(继承自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.

我们可以看到,Mutex没有发布,但是有一些清理,所以坚持使用将是一个很好的方法。

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.

至于你应该如何继续,你当然可以使用try / finally块来确保,如果获得Mutex,它将被正确释放。这可能是最直接的方法。

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.

如果你真的不关心Mutex无法获取的情况(你没有指出,因为你将TimeSpan传递给WaitOne),你可以将Mutex包装在你自己的实现IDisposable的类中,获取Mutex in构造函数(使用没有参数的WaitOne()),并在Dispose中释放它。虽然,我可能不会推荐这个,因为如果出现问题,这会导致你的线程无限期地等待,并且无论是否有充分的理由在尝试获取时明确处理这两种情况,如@HansPassant所述。

#2


34  

This design decision was made a long, long time ago. Over 21 years ago, well before .NET was ever envisioned or the semantics of IDisposable were ever considered. The .NET Mutex class is a wrapper class for the underlying operating system support for mutexes. The constructor pinvokes CreateMutex, the WaitOne() method pinvokes WaitForSingleObject().

很久很久以前就做出了这个设计决定。超过21年前,早在.NET设想或IDisposable的语义被考虑之前。 .NET Mutex类是用于互斥锁的底层操作系统支持的包装类。构造函数pinvokes CreateMutex,WaitOne()方法pinvokes WaitForSingleObject()。

Note the WAIT_ABANDONED return value of WaitForSingleObject(), that's the one that generates the exception.

注意WaitForSingleObject()的WAIT_ABANDONED返回值,即生成异常的返回值。

The Windows designers put the rock-hard rule in place that a thread that owns the mutex must call ReleaseMutex() before it exits. And if it doesn't that this is a very strong indication that the thread terminated in an unexpected way, typically through an exception. Which implies that synchronization is lost, a very serious threading bug. Compare to Thread.Abort(), a very dangerous way to terminate a thread in .NET for the same reason.

Windows设计人员制定了坚如磐石的规则,即拥有互斥锁的线程必须在退出之前调用ReleaseMutex()。如果不是这样,这是一个非常强烈的迹象表明线程以意想不到的方式终止,通常是通过异常。这意味着同步丢失,这是一个非常严重的线程错误。与Thread.Abort()相比,这是一种非常危险的方法,在.NET中以相同的原因终止线程。

The .NET designers did not in any way alter this behavior. Not in the least because there isn't any way to test the state of the mutex other than by performing a wait. You must call ReleaseMutex(). And do note that your second snippet is not correct either; you cannot call it on a mutex that you didn't acquire. It must be moved inside of the if() statement body.

.NET设计者并没有以任何方式改变这种行为。至少是因为除了执行等待之外没有任何方法可以测试互斥锁的状态。您必须调用ReleaseMutex()。并注意你的第二个片段也不正确;你不能用你没有获得的互斥锁来调用它。它必须在if()语句体内移动。

#3


7  

One of the primary uses of a mutex is to ensure that the only code which will ever see a shared object in a state which doesn't satisfy its invariants is the code which (hopefully temporarily) put the object into that state. A normal pattern for code which needs to modify an object is:

互斥锁的主要用途之一是确保在不满足其不变量的状态下看到共享对象的唯一代码是(希望暂时)将对象置于该状态的代码。需要修改对象的代码的正常模式是:

  1. Acquire mutex
  2. 获取互斥锁
  3. Make changes to object which cause its state to become invalid
  4. 对对象进行更改,导致其状态变为无效
  5. Make changes to object which cause its state to become valid again
  6. 对对象进行更改,使其状态再次变为有效
  7. Release mutex
  8. 释放互斥锁

If something goes wrong in after #2 has begun and before #3 has finished, the object may be left in a state which does not satisfy its invariants. Since the proper pattern is to release a mutex before disposing it, the fact that code disposes a mutex without releasing it implies that something went wrong somewhere. As such, it may not be safe for code to enter the mutex (since it hasn't been released), but there's no reason to wait for the mutex to be released (since--having been disposed--it never will be). Thus, the proper course of action is to throw an exception.

如果在#2开始之后和#3完成之前出现问题,则对象可能会处于不满足其不变量的状态。由于正确的模式是在释放互斥体之前释放互斥锁,因此代码在不释放互斥体的情况下处理互斥锁这一事实意味着某些地方出现了问题。因此,代码进入互斥锁可能不安全(因为它尚未被释放),但是没有理由等待释放互斥锁(因为 - 已经被处置 - 它永远不会被释放) 。因此,正确的行动方针是抛出异常。

A pattern which is somewhat nicer than the one implemented by the .NET mutex object is to have the "acquire" method return an IDisposable object which encapsulates not the mutex, but rather a particular acquisition thereof. Disposing that object will then release the mutex. Code can then look something like:

比.NET互斥对象实现的模式稍微好一些的模式是让“获取”方法返回一个IDisposable对象,该对象不封装互斥锁,而是封装其特定的获取。然后处置该对象将释放互斥锁。代码可以看起来像:

using(acq = myMutex.Acquire())
{
   ... stuff that examines but doesn't modify the guarded resource
   acq.EnterDanger();
   ... actions which might invalidate the guarded resource
   ... actions which make it valid again
   acq.LeaveDanger();
   ... possibly more stuff that examines but doesn't modify the resource
}

If the inner code fails between EnterDanger and LeaveDanger, then the acquisition object should invalidate the mutex by calling Dispose on it, since the guarded resource may be in a corrupted state. If the inner code fails elsewhere, the mutex should be released since the guarded resource is in a valid state, and the code within the using block won't need to access it anymore. I don't have any particular recommendations of libraries implementing that pattern, but it isn't particularly difficult to implement as a wrapper around other kinds of mutex.

如果内部代码在EnterDanger和LeaveDanger之间失败,则获取对象应通过调用Dispose对其进行无效,因为受保护的资源可能处于损坏状态。如果内部代码在其他地方失败,则应该释放互斥锁,因为受保护资源处于有效状态,并且使用块中的代码将不再需要访问它。我没有任何特定的库实现该模式的建议,但实现作为其他类型的互斥体的包装并不是特别困难。

#4


7  

Ok, posting an answer to my own question. From what I can tell, this is the ideal way to implement a Mutex that:

好的,发表我自己的问题的答案。据我所知,这是实现Mutex的理想方式:

  1. Always gets Disposed
  2. 总是得到处置
  3. Gets Released iff WaitOne was successful.
  4. 获取释放iff WaitOne成功。
  5. Will not get abandoned if any code throws an exception.
  6. 如果任何代码抛出异常,将不会被放弃。

Hopefully this helps someone out!

希望这可以帮助别人!

using (Mutex mut = new Mutex(false, MUTEX_NAME))
{
    if (mut.WaitOne(new TimeSpan(0, 0, 30)))
    {
        try
        {
           // Some code that deals with a specific TCP port
           // Don't want this to run twice in multiple processes        
        }
        catch(Exception)
        {
           // Handle exceptions and clean up state
        }
        finally
        {
            mut.ReleaseMutex();
        }
    }
}

Update: Some may argue that if the code within the try block puts your resource in an unstable state, you should not release the Mutex and instead let it get abandoned. In other words, just call mut.ReleaseMutex(); when the code finishes successfully, and not put it within the finally block. The code acquiring the Mutex could then catch this exception and do the right thing.

更新:有些人可能会争辩说,如果try块中的代码使您的资源处于不稳定状态,则不应释放Mutex而是让它被放弃。换句话说,只需调用mut.ReleaseMutex();当代码成功完成,而不是将其放在finally块中。获取Mutex的代码可以捕获此异常并执行正确的操作。

In my situation, I'm not really changing any state. I'm temporarily using a TCP port and can't have another instance of the program run at the same time. For this reason, I think my solution above is fine but yours may be different.

在我的情况下,我并没有真正改变任何状态。我暂时使用TCP端口,并且不能同时运行该程序的另一个实例。出于这个原因,我认为我的解决方案很好,但你的解决方案可能会有所不同。

#5


4  

We need to understand more then .net to know what is going on the start of the MSDN page gives the first hint that someone “odd” is going on:

我们需要了解更多.net才能知道MSDN页面开头的内容给出了第一个暗示某人“奇怪”发生的事情:

A synchronization primitive that can also be used for interprocess synchronization.

同步原语,也可用于进程间同步。

A Mutex is a Win32Named Object”, each process locks it by name, the .net object is just a wrapper round the Win32 calls. The Muxtex itself lives within the Windows Kernal address space, not your application address space.

Mutex是一个Win32“命名对象”,每个进程都按名称锁定它.net对象只是Win32调用的一个包装器。 Muxtex本身位于Windows Kernal地址空间内,而不是您的应用程序地址空间。

In most cases you are better off using a Monitor, if you are only trying to synchronizes access to objects within a single process.

在大多数情况下,如果您只是尝试在单个进程中同步对对象的访问,则最好使用Monitor。

#6


3  

If you need to garantee that the mutex is released switch to a try catch finally block and put the mutex release in the finally block. It is assumed that you own and have a handle for the mutex. That logic needs to be included before release is invoked.

如果您需要保证释放互斥锁,请切换到try catch finally块并将互斥锁释放到finally块中。假设您拥有并拥有互斥锁的句柄。在调用release之前,需要包含该逻辑。

#7


2  

Reading the documentation for ReleaseMutex, it seems the design decision was that a Mutex should be released consciously. if ReleaseMutex isn't called, it signifies an abnormal exit of the protected section. putting the release in a finally or dispose, circumvents this mechanism. you are still free to ignore the AbandonedMutexException, of course.

阅读ReleaseMutex的文档,似乎设计决定是应该有意识地释放Mutex。如果未调用ReleaseMutex,则表示受保护部分的异常退出。将发布版本置于最终版本或处置中,绕过此机制。当然,你仍然可以忽略AbandonedMutexException。

#8


2  

Be aware: The Mutex.Dispose() executed by the Garbage collector fails because the garbage collection process does not own the handle according Windows.

请注意:垃圾收集器执行的Mutex.Dispose()失败,因为垃圾收集进程不拥有Windows的句柄。

#9


1  

Dispose depends on WaitHandle to be released. So, even though using calls Dispose, it won't go into affect until the the conditions of stable state are met. When you call ReleaseMutex you're telling the system that you're releasing the resource, and thus, it is free to dispose of it.

Dispose取决于WaitHandle被释放。因此,即使使用调用Dispose,它也不会生效,直到满足稳定状态的条件。当您调用ReleaseMutex时,您告诉系统您正在释放资源,因此可以*处置它。

#1


49  

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 returns a boolean, meaning that acquiring a Mutex can fail (timeout) and both cases must be handled
  • WaitOne返回一个布尔值,这意味着获取互斥锁可能会失败(超时),并且必须处理这两种情况
  • When WaitOne returns true, then the calling thread has acquired the Mutex and must call ReleaseMutex, or else the Mutex will become abandoned
  • 当WaitOne返回true时,调用线程已获取Mutex并且必须调用ReleaseMutex,否则Mutex将被放弃
  • When it returns false, then the calling thread must not call ReleaseMutex
  • 当它返回false时,调用线程不能调用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):

因此,Mutexes比实例化更多。至于你是否应该继续使用,让我们来看看Dispose的作用(继承自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.

我们可以看到,Mutex没有发布,但是有一些清理,所以坚持使用将是一个很好的方法。

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.

至于你应该如何继续,你当然可以使用try / finally块来确保,如果获得Mutex,它将被正确释放。这可能是最直接的方法。

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.

如果你真的不关心Mutex无法获取的情况(你没有指出,因为你将TimeSpan传递给WaitOne),你可以将Mutex包装在你自己的实现IDisposable的类中,获取Mutex in构造函数(使用没有参数的WaitOne()),并在Dispose中释放它。虽然,我可能不会推荐这个,因为如果出现问题,这会导致你的线程无限期地等待,并且无论是否有充分的理由在尝试获取时明确处理这两种情况,如@HansPassant所述。

#2


34  

This design decision was made a long, long time ago. Over 21 years ago, well before .NET was ever envisioned or the semantics of IDisposable were ever considered. The .NET Mutex class is a wrapper class for the underlying operating system support for mutexes. The constructor pinvokes CreateMutex, the WaitOne() method pinvokes WaitForSingleObject().

很久很久以前就做出了这个设计决定。超过21年前,早在.NET设想或IDisposable的语义被考虑之前。 .NET Mutex类是用于互斥锁的底层操作系统支持的包装类。构造函数pinvokes CreateMutex,WaitOne()方法pinvokes WaitForSingleObject()。

Note the WAIT_ABANDONED return value of WaitForSingleObject(), that's the one that generates the exception.

注意WaitForSingleObject()的WAIT_ABANDONED返回值,即生成异常的返回值。

The Windows designers put the rock-hard rule in place that a thread that owns the mutex must call ReleaseMutex() before it exits. And if it doesn't that this is a very strong indication that the thread terminated in an unexpected way, typically through an exception. Which implies that synchronization is lost, a very serious threading bug. Compare to Thread.Abort(), a very dangerous way to terminate a thread in .NET for the same reason.

Windows设计人员制定了坚如磐石的规则,即拥有互斥锁的线程必须在退出之前调用ReleaseMutex()。如果不是这样,这是一个非常强烈的迹象表明线程以意想不到的方式终止,通常是通过异常。这意味着同步丢失,这是一个非常严重的线程错误。与Thread.Abort()相比,这是一种非常危险的方法,在.NET中以相同的原因终止线程。

The .NET designers did not in any way alter this behavior. Not in the least because there isn't any way to test the state of the mutex other than by performing a wait. You must call ReleaseMutex(). And do note that your second snippet is not correct either; you cannot call it on a mutex that you didn't acquire. It must be moved inside of the if() statement body.

.NET设计者并没有以任何方式改变这种行为。至少是因为除了执行等待之外没有任何方法可以测试互斥锁的状态。您必须调用ReleaseMutex()。并注意你的第二个片段也不正确;你不能用你没有获得的互斥锁来调用它。它必须在if()语句体内移动。

#3


7  

One of the primary uses of a mutex is to ensure that the only code which will ever see a shared object in a state which doesn't satisfy its invariants is the code which (hopefully temporarily) put the object into that state. A normal pattern for code which needs to modify an object is:

互斥锁的主要用途之一是确保在不满足其不变量的状态下看到共享对象的唯一代码是(希望暂时)将对象置于该状态的代码。需要修改对象的代码的正常模式是:

  1. Acquire mutex
  2. 获取互斥锁
  3. Make changes to object which cause its state to become invalid
  4. 对对象进行更改,导致其状态变为无效
  5. Make changes to object which cause its state to become valid again
  6. 对对象进行更改,使其状态再次变为有效
  7. Release mutex
  8. 释放互斥锁

If something goes wrong in after #2 has begun and before #3 has finished, the object may be left in a state which does not satisfy its invariants. Since the proper pattern is to release a mutex before disposing it, the fact that code disposes a mutex without releasing it implies that something went wrong somewhere. As such, it may not be safe for code to enter the mutex (since it hasn't been released), but there's no reason to wait for the mutex to be released (since--having been disposed--it never will be). Thus, the proper course of action is to throw an exception.

如果在#2开始之后和#3完成之前出现问题,则对象可能会处于不满足其不变量的状态。由于正确的模式是在释放互斥体之前释放互斥锁,因此代码在不释放互斥体的情况下处理互斥锁这一事实意味着某些地方出现了问题。因此,代码进入互斥锁可能不安全(因为它尚未被释放),但是没有理由等待释放互斥锁(因为 - 已经被处置 - 它永远不会被释放) 。因此,正确的行动方针是抛出异常。

A pattern which is somewhat nicer than the one implemented by the .NET mutex object is to have the "acquire" method return an IDisposable object which encapsulates not the mutex, but rather a particular acquisition thereof. Disposing that object will then release the mutex. Code can then look something like:

比.NET互斥对象实现的模式稍微好一些的模式是让“获取”方法返回一个IDisposable对象,该对象不封装互斥锁,而是封装其特定的获取。然后处置该对象将释放互斥锁。代码可以看起来像:

using(acq = myMutex.Acquire())
{
   ... stuff that examines but doesn't modify the guarded resource
   acq.EnterDanger();
   ... actions which might invalidate the guarded resource
   ... actions which make it valid again
   acq.LeaveDanger();
   ... possibly more stuff that examines but doesn't modify the resource
}

If the inner code fails between EnterDanger and LeaveDanger, then the acquisition object should invalidate the mutex by calling Dispose on it, since the guarded resource may be in a corrupted state. If the inner code fails elsewhere, the mutex should be released since the guarded resource is in a valid state, and the code within the using block won't need to access it anymore. I don't have any particular recommendations of libraries implementing that pattern, but it isn't particularly difficult to implement as a wrapper around other kinds of mutex.

如果内部代码在EnterDanger和LeaveDanger之间失败,则获取对象应通过调用Dispose对其进行无效,因为受保护的资源可能处于损坏状态。如果内部代码在其他地方失败,则应该释放互斥锁,因为受保护资源处于有效状态,并且使用块中的代码将不再需要访问它。我没有任何特定的库实现该模式的建议,但实现作为其他类型的互斥体的包装并不是特别困难。

#4


7  

Ok, posting an answer to my own question. From what I can tell, this is the ideal way to implement a Mutex that:

好的,发表我自己的问题的答案。据我所知,这是实现Mutex的理想方式:

  1. Always gets Disposed
  2. 总是得到处置
  3. Gets Released iff WaitOne was successful.
  4. 获取释放iff WaitOne成功。
  5. Will not get abandoned if any code throws an exception.
  6. 如果任何代码抛出异常,将不会被放弃。

Hopefully this helps someone out!

希望这可以帮助别人!

using (Mutex mut = new Mutex(false, MUTEX_NAME))
{
    if (mut.WaitOne(new TimeSpan(0, 0, 30)))
    {
        try
        {
           // Some code that deals with a specific TCP port
           // Don't want this to run twice in multiple processes        
        }
        catch(Exception)
        {
           // Handle exceptions and clean up state
        }
        finally
        {
            mut.ReleaseMutex();
        }
    }
}

Update: Some may argue that if the code within the try block puts your resource in an unstable state, you should not release the Mutex and instead let it get abandoned. In other words, just call mut.ReleaseMutex(); when the code finishes successfully, and not put it within the finally block. The code acquiring the Mutex could then catch this exception and do the right thing.

更新:有些人可能会争辩说,如果try块中的代码使您的资源处于不稳定状态,则不应释放Mutex而是让它被放弃。换句话说,只需调用mut.ReleaseMutex();当代码成功完成,而不是将其放在finally块中。获取Mutex的代码可以捕获此异常并执行正确的操作。

In my situation, I'm not really changing any state. I'm temporarily using a TCP port and can't have another instance of the program run at the same time. For this reason, I think my solution above is fine but yours may be different.

在我的情况下,我并没有真正改变任何状态。我暂时使用TCP端口,并且不能同时运行该程序的另一个实例。出于这个原因,我认为我的解决方案很好,但你的解决方案可能会有所不同。

#5


4  

We need to understand more then .net to know what is going on the start of the MSDN page gives the first hint that someone “odd” is going on:

我们需要了解更多.net才能知道MSDN页面开头的内容给出了第一个暗示某人“奇怪”发生的事情:

A synchronization primitive that can also be used for interprocess synchronization.

同步原语,也可用于进程间同步。

A Mutex is a Win32Named Object”, each process locks it by name, the .net object is just a wrapper round the Win32 calls. The Muxtex itself lives within the Windows Kernal address space, not your application address space.

Mutex是一个Win32“命名对象”,每个进程都按名称锁定它.net对象只是Win32调用的一个包装器。 Muxtex本身位于Windows Kernal地址空间内,而不是您的应用程序地址空间。

In most cases you are better off using a Monitor, if you are only trying to synchronizes access to objects within a single process.

在大多数情况下,如果您只是尝试在单个进程中同步对对象的访问,则最好使用Monitor。

#6


3  

If you need to garantee that the mutex is released switch to a try catch finally block and put the mutex release in the finally block. It is assumed that you own and have a handle for the mutex. That logic needs to be included before release is invoked.

如果您需要保证释放互斥锁,请切换到try catch finally块并将互斥锁释放到finally块中。假设您拥有并拥有互斥锁的句柄。在调用release之前,需要包含该逻辑。

#7


2  

Reading the documentation for ReleaseMutex, it seems the design decision was that a Mutex should be released consciously. if ReleaseMutex isn't called, it signifies an abnormal exit of the protected section. putting the release in a finally or dispose, circumvents this mechanism. you are still free to ignore the AbandonedMutexException, of course.

阅读ReleaseMutex的文档,似乎设计决定是应该有意识地释放Mutex。如果未调用ReleaseMutex,则表示受保护部分的异常退出。将发布版本置于最终版本或处置中,绕过此机制。当然,你仍然可以忽略AbandonedMutexException。

#8


2  

Be aware: The Mutex.Dispose() executed by the Garbage collector fails because the garbage collection process does not own the handle according Windows.

请注意:垃圾收集器执行的Mutex.Dispose()失败,因为垃圾收集进程不拥有Windows的句柄。

#9


1  

Dispose depends on WaitHandle to be released. So, even though using calls Dispose, it won't go into affect until the the conditions of stable state are met. When you call ReleaseMutex you're telling the system that you're releasing the resource, and thus, it is free to dispose of it.

Dispose取决于WaitHandle被释放。因此,即使使用调用Dispose,它也不会生效,直到满足稳定状态的条件。当您调用ReleaseMutex时,您告诉系统您正在释放资源,因此可以*处置它。