.net 难以置信的逻辑线程数量;windbg can';你没看见他们吗?

.net 难以置信的逻辑线程数量;windbg can';你没看见他们吗?,.net,debugging,windbg,.net,Debugging,Windbg,我有一个进程显示了约4294965900个“当前逻辑线程”(根据性能计数器)和约400个物理线程 我已经使用ADPlus(-hang)创建了一个内存转储,windbg(!threads)只显示物理线程 如何找出所有这些逻辑线程的来源?这在我看来似乎是一个可疑的高数字 表示为无符号32位整数的数字-1396是4294965900,1396看起来更合理 某个地方可能有bug?因为您的进程正在运行托管代码,所以逻辑线程计数很可能是指CLR线程。Net在CLR逻辑线程和物理线程之间进行映射。要进一步调查

我有一个进程显示了约4294965900个“当前逻辑线程”(根据性能计数器)和约400个物理线程

我已经使用ADPlus(-hang)创建了一个内存转储,windbg(!threads)只显示物理线程


如何找出所有这些逻辑线程的来源?

这在我看来似乎是一个可疑的高数字

表示为无符号32位整数的数字-1396是4294965900,1396看起来更合理


某个地方可能有bug?

因为您的进程正在运行托管代码,所以逻辑线程计数很可能是指CLR线程。Net在CLR逻辑线程和物理线程之间进行映射。要进一步调查此问题,您可以使用!Windbg中的threads命令。以下是此命令的输出示例:


0:028> !threads
ThreadCount:      25
UnstartedThread:  0
BackgroundThread: 22
PendingThread:    0
DeadThread:       3
Hosted Runtime:   yes
                                   PreEmptive   GC Alloc                Lock
       ID  OSID ThreadOBJ    State GC           Context       Domain   Count APT Exception
   0    1  12b0 007b69d0      4220 Enabled  120337b4:12034a3c 007afef8     0 STA
   6    2  1f70 007c2688      b220 Enabled  11ed2a84:11ed4a3c 007afef8     0 MTA (Finalizer)
   7    3  2340 007c8ac8      1220 Enabled  00000000:00000000 007afef8     0 Ukn
  11    4  1c4c 0aaf3380      7220 Enabled  00000000:00000000 007afef8     0 STA
  13    8  2414 0d4932f0       220 Enabled  00000000:00000000 007afef8     0 Ukn
   3    a  2780 0d4d08e8   1009220 Enabled  00000000:00000000 007afef8     0 MTA (Threadpool Worker)
  15    7   970 0d4d0df0   1009220 Enabled  11ed4ad8:11ed6a3c 007afef8     0 MTA (Threadpool Worker)
  19    9  2510 0d4d12f8   200b220 Enabled  00000000:00000000 007afef8     0 MTA
  20    b   80c 0d4d1800   200b220 Enabled  00000000:00000000 007afef8     0 MTA
  21    c  2490 0d4d1d08   200b220 Enabled  00000000:00000000 007afef8     0 MTA
  23    d  2724 0d4d2210   1009220 Enabled  00000000:00000000 007afef8     0 MTA (Threadpool Worker)
  24    e  2200 0d4d2718   1009220 Enabled  00000000:00000000 007afef8     0 MTA (Threadpool Worker)
  26    f  1f3c 0d4d2c20   1009220 Enabled  00000000:00000000 007afef8     0 MTA (Threadpool Worker)
  25   10  200c 0d4d3128   1009220 Enabled  00000000:00000000 007afef8     0 MTA (Threadpool Worker)
  27   11  2708 0d4d3630   1009220 Enabled  00000000:00000000 007afef8     0 MTA (Threadpool Worker)
  17    6  21b4 0d4d3b38   1009220 Enabled  00000000:00000000 007afef8     0 MTA (Threadpool Worker)
  18    5  2148 0d4d4548       220 Enabled  00000000:00000000 007afef8     0 MTA
XXXX   16       0d4d6378     19820 Enabled  00000000:00000000 007afef8     0 MTA
XXXX   15       0d4d5e70     19820 Enabled  00000000:00000000 007afef8     0 MTA
  30   14  112c 0d4d5968   200b220 Enabled  00000000:00000000 007afef8     0 MTA
  32   13  2734 0d4d5460      b220 Enabled  00000000:00000000 007afef8     0 MTA
  33   12  11ec 0d4d4a50   100a220 Enabled  00000000:00000000 007afef8     0 MTA (Threadpool Worker)
  34   17  166c 0d4d6880   8009220 Enabled  00000000:00000000 007afef8     0 MTA (Threadpool Completion Port)
  35   18  24f4 0d4d6d88   8009220 Enabled  00000000:00000000 007afef8     0 MTA (Threadpool Completion Port)
XXXX   19       0d4d7798     19820 Enabled  00000000:00000000 007afef8     0 Ukn
注意:在输出的顶部,它打印出统计数据。如果您发现大量的死线程,这可能表明资源泄漏。签出此类型的资源泄漏

在这个世界上!线程输出左列是非托管线程ID(与
~
命令显示的相同),第二列是CLR线程ID,第三列是OS线程ID

如何找出所有这些逻辑线程的来源

他们不是。他们不存在。你不可能有任何类型的40亿个线程,除非你运行在一台64位的机器上,至少有几PB的RAM

每个线程,无论是“物理”操作系统线程还是由某个框架提供的线程,都至少需要某种标识符。如果这是一个32位的数字,那么仅仅存储这些标识符将占用近16GB的RAM。(当然,还剩下大约1600个未使用的标识符)。如果标识符为64位宽,则需要32GB RAM。除此之外,每个线程都需要一些堆栈空间(一个常见的默认值是1MB,这使我们最多有4 PB的内存)

这是一只虫子。线程不存在,性能计数器出于某种原因向您报告垃圾值

例如,它可能是一个负错误代码,当转换为无符号整数时,它会变成这个巨大的数字


或者可能是其他一些错误情况。

我这周也有同样的问题,同样的症状。这是真的。是的,我的服务器令人印象深刻,128G Ram和24核

这里的问题确实是逻辑线程。如果CLR可以避免,它就不会创建真正的线程。我有一个定期重新激活的计时器,比如
Timer.Change(10000,10000)
,在计时器回调中,我的代码挂在网络上,这让CLR运行时知道这个“物理线程”可以重用。10秒后,计时器再次触发,并创建一个新的逻辑线程,依此类推。下一个问题是,我的其余代码完全使用了任务,而这些任务也使用了逻辑线程。将所有这些结合起来,您将在一两周内产生数十亿个逻辑线程的连锁反应

我的解决方法很简单:使计时器不再重复,但只在前一个计时器触发器完成后重新安排下一个计时器触发器:
timer.Change(10000,Timeout.Infinite)
并进行计时器回调,以便在某个合理的超时时取消io。

并且重申,是的,当然这是一个可疑的高数字。这就是为什么我要找出他们在哪里。记住,WinDbg只显示了约400个物理线程,所以不,我认为实际上没有约1400个线程。我没有得到升级票?你怎么会有负数的线程?这个数字来自Windows性能计数器,它是一个64位的数字。@马克:因为这个小小的负数是报告这个高得离谱数字的合理解释-例如,1396可能是一个错误代码。@jalf:现在你提到它,错误代码听起来确实是一个合理的解释。第一个数字看起来像是一个bug,但即使是400个线程也太多了,除非它运行在一个巨大的多核服务器上。我在项目中包括MS SQL Express 2005时看到了这一点,您的代码中是否有MS SQL访问权限,是否可以删除这些权限以查看逻辑线程是否是由于这些权限造成的?它运行在一台令人印象深刻的服务器上。@Mark您是否知道为什么会发生这种情况?@StephanRyer我没有,对不起。好的,您会注意到我这样做了,并且只显示了物理线程。