2

当一个线程到达一个线程时,有没有一种快速的方法来记录一个线程正在等待一个锁?

lock(x)
{
  //do work on a collection

}

?

如果线程 1 到达锁,并且块中没有另一个线程,则应该没有日志。那么如果线程 2 到达 lock(x) 并且线程 1 仍然在块中,那么应该有一个日志。理想的解决方案不需要切换到 Mutex 或 Monitor 会增加太多复杂性。如果有一种使用 TPL、PLINQ 或 RX 的快速简便的方法来做到这一点,那就太好了。

4

3 回答 3

10

您可以对语句进行脱糖lock并使用Monitor.TryEnter检查是否可以在不等待的情况下获取锁:

bool lockTaken = false;
var obj = x;
try
{
    Monitor.TryEnter(obj, ref lockTaken);
    if (!lockTaken)
    {
        Log();
        Monitor.Enter(obj, ref lockTaken);
    }
    //do work on a collection
}
finally
{
    if (lockTaken)
    {
        Monitor.Exit(obj);
    }
}
于 2011-10-12T15:32:10.403 回答
2

lock()使用标准语句,您将无法轻松做到这一点。您可以使用Monitor.TryEnter()来尝试进入锁,然后在方法返回时记录一些内容false

于 2011-10-12T15:30:48.640 回答
2

你为什么要这样做?如果是出于调试或分析目的,您可以使用非托管 CLR 分析或调试 API。另一个想法是在使用 PostSharp 或 Afterthought 等工具编译后静态修改 IL 代码。(请注意,Afterthought 无法以当前的形式执行此操作,但由于您有源代码,因此您可以破解它。)

我建议您改为修改代码。我推荐这个而不是 dtb 的语法:

if (!Monitor.TryEnter(x))
{
    Log();
    Monitor.Enter(x);
}
try
{
    //do work on a collection
}
finally
{
    Monitor.Exit(x);
}
于 2011-10-12T15:48:55.577 回答