我们在生产中有一个C#控制台应用程序,它具有间歇性的线程死锁。我试图通过将VS 2017附加到正在运行的进程来找到死锁,但我找不到任何方法来轻松找到死锁的原因。似乎没有任何窗口可以识别哪些线程拥有哪些锁。 (我尝试使用Memory窗口,但这根本不起作用。)
我也尝试过使用Dump文件,但发现很难理解它显示的内容。 (但这是在我知道我正在寻找僵局之前。)
我习惯于在Java中使用JStack,这是一个命令行实用程序,用于运行Java应用程序,它打印一个Thread转储,并识别死锁,并在每个StackTrace中显示一个Thread锁定监视器的点。
是否有一些与.NET相同的工具?
答案 0 :(得分:3)
我使用WinDbg检查发生死锁时从进程中获取的完整userdump。确保您具有确切的二进制文件(DLL-s和PDB-s)以及转储文件。使用适当的WinDbg版本作为二进制文件(32位或64位)。
使用File
- > Open crash dump...
命令打开您的转储,这将打开一个"控制台" WinDbg中的窗口。您可以通过在底部输入区域中键入命令来使用它。您可以通过在Edit
菜单中记录所有WinDbg输出来保存它。
您可以使用.loadby sos clr
加载SOS扩展,然后使用!EEStack
获取所有调用堆栈。您可以尝试使用-short
参数来查看是否在线程顶部发现了相同的函数。
正如@ dmitry-egorov在评论中建议的那样,您也可以使用SOSEX的!dlk
。
当您正在寻找可能导致死锁的功能时,请查找您的功能 - 它们可能不在堆栈顶部但会关闭 - 您的某些功能可能会尝试以不同的顺序使用2个不同的锁并且它们会死锁。