可以Monitor.Enter抛出异常吗?

时间:2012-01-12 18:22:50

标签: c# multithreading synchronization

Monitor.Enter可以抛出任何异常。我正在进行代码审查,并在try block之前发现Monitor.Enter。你看到有什么问题吗?

Monitor.Enter(...)
try
{
    ...
}
finally
{
    Monitor.Exit(..)
}

4 个答案:

答案 0 :(得分:13)

这是正确的模式,无论Enter()是否抛出(可以抛出)。

只有在致电Enter()成功后,您的代码才有权致电Exit()

假设对Enter()的调用失败。然后调用相应的Exit()是不正确的,这将使事情变得更糟。所以Enter()必须在try块之外(之前)。

答案 1 :(得分:10)

Hans Passant的评论当然是正确的。如果Monitor.Enter在锁定之前抛出,那么您希望最终运行。如果在之后引发并且在之后输入了尝试,则释放锁定。 (稍后详细介绍。)但是如果在锁定之后发生抛出但之前输入了尝试,那么锁定永远不会被清除。

This is a rare but possible situation.

在C#4中,我们更改了lock语句的codegen,以便监视器输入在try中。这可确保在锁定后抛出某些东西时始终释放锁定。但是,请注意这可能仍然是错误的。如果在锁定之后抛出某些东西,则锁定正在保护的任何非原子突变可能是半完成的,然后finally块解锁锁定并允许访问不一致的状态!这里的根本问题是你不应该首先扔进锁内。

有关详细讨论,请参阅my article about the issue

答案 2 :(得分:1)

Monitor.Enter至少可以抛出以下异常

  • 参数的ArgumentNullException是null
  • ThreadInterruptedException如果执行Enter的线程调用了它的Interrupt方法。

答案 3 :(得分:0)

如果它获得了锁定,那么没有。

但可能会在Monitor.Entertry块之间抛出异常。

推荐的方法是新的Enter方法,.NET 4中的新方法:

public static void Enter( obj, ref bool lockTaken )