2016-06-16 20 views
0

我想知道一个调用Monitor.TryEnter的故障安全方法。 文档显示它是这样的:如何调用Monitor.TryEnter

if (Monitor.TryEnter(lockObj)) { 
    try { 
     // The critical section. 
    } 
    finally { 
     // Ensure that the lock is released. 
     Monitor.Exit(lockObj); 
    } 
} 

由于这是“官方”的方式来称呼它,我毫不犹豫地做任何事情。但我不觉得很舒服代码: 假设我们得到这样一个ThreadAbortException:

if (Monitor.TryEnter(lockObj)) { 
    // *** ThreadAbortException happens exactly here 
    try { 
     [...] 
    } 
    finally { [...] } 
} 

这是否不会离开我是永远不会释放锁?

+0

为什么不使用'lock(lockObj){...}'而不是?此外,ThreadAbortException通常不是问题,因为无论如何,流程/ appdomain都将被拆除。 –

+0

@Lasse:当锁已被占用时,锁将不允许我做别的事情。 threadAbortException不仅在进程被拆除时发生,还有更多的方法来终止线程。 –

回答

2

你说得对。因此推荐使用Monitor.TryEnter的方式是:

bool lockAcquired; 

try 
{ 
    Monitor.TryEnter(lockObj, ref lockAcquired); 

    if (lockAcquired) 
    { 
     DoSomething(); 
    } 
} 
finally 
{ 
    if (lockAcquired) 
    { 
     Monitor.Exit(lockObj); 
    } 
} 
+0

谢谢!我认为TryEnter(lock)的代码是建议的代码,但现在我发现那是不太优选的重载的首选代码。 –

0

它可以。你可以用finally试块封闭所有Monitor(带有布尔超载)。

关于你的ThreadAbortException的例子,这是一个特殊的例子。 如果在卸载应用程序域后CLR抛出,CLR会照顾你做它需要的东西,并且在此应用程序域中将不会运行任何代码,因此你不必担心。

如果你手动把它,以任何方式,你将在一个糟糕的状态...

至于侧面说明看一看here,关于编码器在锁定的情况下释放的信任的例外。