Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Monitor.TryEnter(锁定对象、超时)重载是否不安全?(.net)_C# - Fatal编程技术网

C# Monitor.TryEnter(锁定对象、超时)重载是否不安全?(.net)

C# Monitor.TryEnter(锁定对象、超时)重载是否不安全?(.net),c#,C#,在代码审查期间,有人建议我这样做 bool acquiredLock = false; try { Monitor.TryEnter(lockObject, 500, ref acquiredLock); if (acquiredLock) { // do something } else { // fallback strategy } } finally { if (acquiredLock) {

在代码审查期间,有人建议我这样做

bool acquiredLock = false;
try {
    Monitor.TryEnter(lockObject, 500, ref acquiredLock);
    if (acquiredLock) {
        // do something
    }
    else {
        // fallback strategy
   }
}
finally
{
    if (acquiredLock)
    {
        Monitor.Exit(lockObject);
    }
}
而不是简单的

if (Monitor.TryEnter(lockObject, 500)) {
      try {
          // do something...
      } 
      finally {
          Monitor.Exit(lockObject);
      }
} else {
     // fallback strategy
}

这有什么区别?如果第二个代码会出现错误,那么第一个代码怎么可能不会出现错误呢?

当第二个代码没有出现时,您的第一个代码片段正在退出监视器。你想在完成关键块后释放监视器。

除了其他海报提出的关于退出的完全有效的观点之外。。。声明它可以抛出三个异常中的一个,因此从技术上讲,它可以在特定情况下轰炸您的应用程序。

即使该方法名为
TryEnter
,它实际上抛出异常,您需要正确处理它们。如果它抛出一个异常,而您不处理它并释放监视器,则可能出现死锁情况

这可能有点过于谨慎,因为若您查看它实际抛出的异常,它很可能会在尝试获取锁之前抛出它们。但这是一个实现细节,您无法确定


您可能可以在上检查此方法是如何实现的,但正如我所说,这是一个实现细节。

假设您在第二个代码片段中实际调用了
Monitor.Exit
,差异将在中解释:

此重载始终设置传递给
ref
参数
locktaked
的变量值,即使该方法引发异常,因此变量值是测试是否必须释放锁的可靠方法

换句话说,对于第二个代码段,在获取锁之后但在方法返回之前抛出异步异常(例如,正在中止的线程)是可行的。即使使用
finally
块,也无法轻松判断是否需要释放锁。使用
ref
参数,“获取监视器”和“
ref
参数设置为
true
”操作是原子的-当方法退出时,变量不可能有错误的值,但是它退出了


从C#4开始,当针对支持此重载的平台时,这也是C#编译器生成的代码。

因为您从未退出锁?@SLaks抱歉,这是由于问题中的错误。这不是真正的问题。我会解决这个问题。如果代码仍然正常工作,您必须在混合中抛出一个Thread.Abort(),并进行推理。背景,x64抖动需要搞乱它。可能是一个重复的是,这看起来像一个重复对我来说,即使所有的功能签名是不同的!对不起,那是因为问题中的一个错误。这不是真正的问题。我来解决这个问题。那些记录在案的异常都是参数验证异常。在获得锁后,您似乎不太可能获得任何一个。但是:语句Monitor.TryEnter没有包含在捕获这些验证异常的内容中,至少没有包含在显示的代码段中。它可能会在运行时爆炸。我的意思是,如果你得到任何一个异常,显然你没有锁。您甚至不需要ref locktaked参数来知道这一点。