在C#中,如何使用try catch块安全地退出锁?

以下是使用try-catch块在锁内发生exception的示例。

int zero = 0; int j = 10; lock (sharedResource.SyncRoot) { try { j = j / zero; } catch (DivideByZeroException e) { // exception caught but lock not released } } 

如何在捕获中安全地释放此锁定?

它不会自动发布吗?

从MSDN锁定手段

 System.Threading.Monitor.Enter(x); try { ... } finally { System.Threading.Monitor.Exit(x); } 

所以你不必费心。

在您超出锁定(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. } 

certificate。

 .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 

Jaredpar在评论中发布了一个链接,我认为值得一试:

http://blogs.msdn.com/ericlippert/archive/2009/03/06/locks-and-exceptions-do-not-mix.aspx

在这篇博文中,Eric Lippert评论了与锁定C#相关的问题:

这里的问题是,如果编译器在监视器输入和try-protected区域之间生成无操作指令,那么运行时可能会在监视器输入之后但在尝试之前抛出线程中止exception。 在那种情况下,终于永远不会运行,所以锁泄漏,可能最终导致程序死锁。 如果在未优化和优化的构建中这是不可能的,那将是很好的。

你的代码非常好。 lock(sth){...}在内部转换为try finally块。

锁定将在其块的上下文退出时释放,但是会发生这种情况。 在上面给出的代码示例中,当控件退出最终的上下文时,锁将自动安全地释放。

无论如何都不会这样运行:

 try { lock (sharedResource.SyncRoot) { int bad = 2 / 0; } } catch (DivideByZeroException e) { // exception caught but lock not released } finally { //release lock }