当一个线程到达一个线程时,有没有一种快速的方法来记录一个线程正在等待一个锁?
lock(x)
{
//do work on a collection
}
?
如果线程 1 到达锁,并且块中没有另一个线程,则应该没有日志。那么如果线程 2 到达 lock(x) 并且线程 1 仍然在块中,那么应该有一个日志。理想的解决方案不需要切换到 Mutex 或 Monitor 会增加太多复杂性。如果有一种使用 TPL、PLINQ 或 RX 的快速简便的方法来做到这一点,那就太好了。
当一个线程到达一个线程时,有没有一种快速的方法来记录一个线程正在等待一个锁?
lock(x)
{
//do work on a collection
}
?
如果线程 1 到达锁,并且块中没有另一个线程,则应该没有日志。那么如果线程 2 到达 lock(x) 并且线程 1 仍然在块中,那么应该有一个日志。理想的解决方案不需要切换到 Mutex 或 Monitor 会增加太多复杂性。如果有一种使用 TPL、PLINQ 或 RX 的快速简便的方法来做到这一点,那就太好了。
您可以对语句进行脱糖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);
}
}
lock()
使用标准语句,您将无法轻松做到这一点。您可以使用Monitor.TryEnter()
来尝试进入锁,然后在方法返回时记录一些内容false
。
你为什么要这样做?如果是出于调试或分析目的,您可以使用非托管 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);
}