我有一个报告大量逻辑线程的服务。来自PerfMon:
.NET CLR LocksAndThreads -> # of current logical threads: 663
.NET CLR LocksAndThreads -> # of current physical threads: 659
Process -> Thread Count: 15
这太高了,所以我捕获了一个内存转储(通过sysinternals procdump.exe)并从Visual Studio打开它(Debug with Mixed)。一旦所有内容都被加载,我查看了线程窗口,它只显示了15个OS线程,而不是.net物理或.net逻辑。该服务本身是一个承载4个WCF服务的Windows服务(System.ServiceModel.ServiceHost)。
我如何找出这些线程是什么,以便我可以修复代码并摆脱它们? 如何让visual studio识别和显示逻辑线程? 它是Visual Studio的问题,还是转储本身的问题?
答案 0 :(得分:2)
首先,您需要获取内存转储。有很多种方法可以做到这一点。我发现的最简单的一个是procdump.exe,它是SysInternals的一部分,提供文档here。
接下来,您需要下载并安装WinDbg并使SOS正常工作(SOS是让您查看.net托管进程的模块)。有关设置的更多信息可用here。如果从服务器获得转储(就像我的情况那样),那么.net版本可能稍微关闭,并且SOS将无法与转储文件一起正常工作。如果发生这种情况,您需要根据this评论将源.net版本中的一些相关文件复制到windbg安装中。
设置好所有内容并加载转储后,运行命令:
!threads
这应该为您提供.net逻辑线程列表。另外值得注意的是,在线程列表之前,它会给你一个摘要。对于这个问题很重要,DeadThread非常高(600+)。这表明线程已经完成,但是它们所持有的内存(堆栈)无法释放。
在我的特定情况下,我发现挂起的线程是来自WCF线程池的线程,它不能通过GC,因为其他线程持有对它的引用。当其他线程不再需要它时,我将其他线程更改为将父线程置空,并且允许它正确地获取GC。