您可以使用WinDbg检查应用程序中的线程.以下是您可以做的简要计划.
应用程序挂起时,将WinDbg文件复制到计算机.
将WinDbg附加到进程或使用ADPlus获取进程的挂起转储.如果选择ADPlus,则在WinDbg中加载转储.
从WinDbg加载sos.dll,以便检查托管代码.
该!threads
命令将显示应用程序和!clrstack
命令中的所有线程,将显示它们正在执行的操作.使用~e!clrstack
转储全部线程的调用堆栈.查找Wait方法的调用,因为它们表示锁定.
该!syncblk
命令将为您提供有关哪些线程持有不同锁的信息.
要找出给定线程尝试获取的锁定,请切换到该线程并检查堆栈对象(!dso
).从这里你应该能够找到线程试图获取的锁.
澄清:WinDbg不需要定期安装.只需复制文件.此外,如果您执行挂起转储,则可以根据需要继续在另一台计算机上进行调试.
增加:Sosex具有!dlk
在许多情况下自动识别死锁的命令.它不会一直有效,但是当它发生时,它会为你完成所有的工作,所以这应该是你的第一选择.
您可以使用WinDbg检查应用程序中的线程.以下是您可以做的简要计划.
应用程序挂起时,将WinDbg文件复制到计算机.
将WinDbg附加到进程或使用ADPlus获取进程的挂起转储.如果选择ADPlus,则在WinDbg中加载转储.
从WinDbg加载sos.dll,以便检查托管代码.
该!threads
命令将显示应用程序和!clrstack
命令中的所有线程,将显示它们正在执行的操作.使用~e!clrstack
转储全部线程的调用堆栈.查找Wait方法的调用,因为它们表示锁定.
该!syncblk
命令将为您提供有关哪些线程持有不同锁的信息.
要找出给定线程尝试获取的锁定,请切换到该线程并检查堆栈对象(!dso
).从这里你应该能够找到线程试图获取的锁.
澄清:WinDbg不需要定期安装.只需复制文件.此外,如果您执行挂起转储,则可以根据需要继续在另一台计算机上进行调试.
增加:Sosex具有!dlk
在许多情况下自动识别死锁的命令.它不会一直有效,但是当它发生时,它会为你完成所有的工作,所以这应该是你的第一选择.
您也可以使用"TimedLock"结构,而不是使用常规lock
和Monitor.Enter
方法来锁定某些数据.如果无法及时获取锁定,则此TimedLock会抛出异常,如果您有一些未释放的锁定,它也会发出警告.
此文章由Ian Griffiths的也许可以帮助.
并发编程中的超时是一个可怕的想法.这导致非确定性,从而导致无法再现的行为.尝试使用像CHESS这样的死锁检测工具.更好的是,最小化使用无锁算法的锁的数量,或完全避开锁并将程序划分为单线程隔离区并使用队列在隔离专区之间传递数据(更好地称为消息传递/ actor并发).