以下是使用try-catch块在锁内发生异常的示例。
int zero = 0;
int j = 10;
lock (sharedResource.SyncRoot)
{
try
{
j = j / zero;
}
catch (DivideByZeroException e)
{
// exception caught but lock not released
}
}
如何在捕获中安全释放此锁?
答案 0 :(得分:36)
不会自动发布吗?
来自MSDN锁定手段
System.Threading.Monitor.Enter(x);
try {
...
}
finally {
System.Threading.Monitor.Exit(x);
}
所以你不必费心。
答案 1 :(得分:13)
在您超出锁定(sharedResource.SyncRoot)块的范围之前,不会释放锁定。 lock (sharedResource.SyncRoot) {}
基本上与:
Monitor.Enter(sharedResource.SyncRoot);
try
{
}
finally
{
Monitor.Exit(sharedResource.SyncRoot);
}
如果您想要更多控制权,可以自己进入/退出,或者只是将锁定重新锁定到您想要的位置,例如:
try
{
lock(sharedResource.SyncRoot)
{
int bad = 2 / 0;
}
}
catch (DivideByZeroException e)
{
// Lock released by this point.
}
答案 2 :(得分:6)
证明。
.method public hidebysig instance void test(int32 i) cil managed
{
// Code size 43 (0x2b)
.maxstack 2
.locals init ([0] int32 bad,
[1] class [mscorlib]System.DivideByZeroException e,
[2] object CS$2$0000)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld object WebApplication1.myclass::mutex
IL_0007: dup
IL_0008: stloc.2
IL_0009: call void [mscorlib]System.Threading.Monitor::Enter(object)
IL_000e: nop
.try
{
IL_000f: nop
.try
{
IL_0010: nop
IL_0011: ldc.i4.2
IL_0012: ldarg.1
IL_0013: div
IL_0014: stloc.0
IL_0015: nop
IL_0016: leave.s IL_001d
} // end .try
catch [mscorlib]System.DivideByZeroException
{
IL_0018: stloc.1
IL_0019: nop
IL_001a: nop
IL_001b: leave.s IL_001d
} // end handler
IL_001d: nop
IL_001e: nop
IL_001f: leave.s IL_0029
} // end .try
finally
{
IL_0021: ldloc.2
IL_0022: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_0027: nop
IL_0028: endfinally
} // end handler
IL_0029: nop
IL_002a: ret
} // end of method myclass::test
答案 3 :(得分:5)
Jaredpar在评论中发布了一个链接,我认为值得一试:
http://blogs.msdn.com/ericlippert/archive/2009/03/06/locks-and-exceptions-do-not-mix.aspx
在这篇博文中,Eric Lippert评论了与锁定C#相关的问题:
这里的问题是,如果 编译器生成无操作指令 显示器之间进入和 尝试保护区域然后它 运行时可以抛出一个 线程中止后的异常 监视器输入但在尝试之前。在 那个场景,终于永远不会运行 所以锁可能最终泄漏 使该计划陷入僵局。这将是 很好,如果这是不可能的 未经优化和优化的构建。
答案 4 :(得分:3)
你的代码非常好。 lock(sth){...}
内部翻译为try finally
块。
答案 5 :(得分:1)
无论如何都不会这样运行:
try
{
lock (sharedResource.SyncRoot)
{
int bad = 2 / 0;
}
}
catch (DivideByZeroException e)
{
// exception caught but lock not released
}
finally
{
//release lock
}
答案 6 :(得分:1)
当退出锁定的上下文时,锁定将被释放,但是会发生这种情况。在上面给出的代码示例中,当控件退出最终的上下文时,锁将自动安全地释放。