C# 当线程等待到达lock语句时记录日志

C# 当线程等待到达lock语句时记录日志,c#,locking,system.reactive,task-parallel-library,plinq,C#,Locking,System.reactive,Task Parallel Library,Plinq,有没有一种快速的方法来记录线程在到达某个位置时正在等待锁 lock(x) { //do work on a collection } ? 如果线程1到达锁,并且块中没有其他线程,那么应该没有日志。然后,如果线程2到达锁(x)并且线程1仍然在块中,那么应该有一个日志。理想的解决方案不需要切换到互斥体或监视器,这会增加很多复杂性。如果有一种使用TPL、PLINQ或RX快速简便的方法,那就太好了。使用标准的lock()语句,您将无法轻松做到这一点。您可以使用尝试输入锁,然后在方法返回false

有没有一种快速的方法来记录线程在到达某个位置时正在等待锁

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

}
?


如果线程1到达锁,并且块中没有其他线程,那么应该没有日志。然后,如果线程2到达锁(x)并且线程1仍然在块中,那么应该有一个日志。理想的解决方案不需要切换到互斥体或监视器,这会增加很多复杂性。如果有一种使用TPL、PLINQ或RX快速简便的方法,那就太好了。

使用标准的
lock()
语句,您将无法轻松做到这一点。您可以使用尝试输入锁,然后在方法返回
false

时记录一些内容。您可以使用来检查是否可以在不等待的情况下获取锁:

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);
    }
}

你为什么要这么做?如果是出于调试或分析目的,则可以使用非托管CLR分析或调试API。另一个想法是在使用PostSharp或Posthough等工具编译后静态修改IL代码。(请注意,“事后思考”在其当前形式下无法做到这一点,但由于您拥有源代码,您可以将其破解。)

我建议您修改代码。我建议使用以下语法,而不是dtb的语法:

if (!Monitor.TryEnter(x))
{
    Log();
    Monitor.Enter(x);
}
try
{
    //do work on a collection
}
finally
{
    Monitor.Exit(x);
}

我认为您必须将
简写扩展为它的长写等价物,并手动插入日志。当我说理想的解决方案不需要切换到互斥体时,我的意思是它不需要显式使用互斥体或监视器。我编辑了最初的问题以反映这一点。我确实需要这个,只是为了调试,并且希望语法尽可能简单。那么PostSharp就是一个不错的选择。