为什么WinDbg,任务管理器和VS调试器报告的线程数不同?

时间:2010-02-10 22:49:21

标签: .net multithreading windbg

当我的.Net 3.5应用程序运行时,Windows任务管理器显示我的应用程序有16个线程。我为进程收集了一个内存转储,并使用WinDbg / SOS打开它。

运行!threads命令显示我有:

ThreadCount: 456
UnstartedThread: 0
BackgroundThread: 6
PendingThread: 0
DeadThread: 449
Hosted Runtime: no

以下是!threads输出的前几行:

       ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception
   0    1 2848 004366a8      6020 Enabled  11738178:11738778 0042a9f0     0 STA
   2    2 1820 004430e0      b220 Enabled  00000000:00000000 0042a9f0     0 MTA (Finalizer)
   7    5 2c38 055d6330    80a220 Enabled  00000000:00000000 0042a9f0     0 MTA (Threadpool Completion Port)
   8    4  e18 04116900   180b220 Enabled  1157cdc8:1157e778 0042a9f0     0 MTA (Threadpool Worker)
XXXX    6    0 055f94b0      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX    7    0 05649228      9820 Enabled  00000000:00000000 0042a9f0     0 MTA
XXXX    8    0 0567d4f8      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX    9    0 05688d68      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX    a    0 056fd680      9820 Enabled  00000000:00000000 0042a9f0     0 MTA
XXXX    b    0 0575d7f0      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX    c    0 056fd250      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX    d    0 0572a780      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX    e    0 0f082668      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX    f    0 0f082a38      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   10    0 0570ca68      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   11    0 0570ce50      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
  10   12 3fb0 0570d238   180b220 Enabled  00000000:00000000 0042a9f0     0 MTA (Threadpool Worker)
XXXX   13    0 0570d620      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   14    0 0570da08      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   15    0 0570ddf0      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   16    0 0570e1d8      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   17    0 0570e5c0      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   18    0 0579e540      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   19    0 0579e928      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   1a    0 0579ed10      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   1b    0 0579f0f8      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   1c    0 0579f4e0      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   1d    0 0579f8c8      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   1e    0 0579fcb0      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   1f    0 057a0098      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn
XXXX   20    0 057a0480      9820 Enabled  00000000:00000000 0042a9f0     0 Ukn

如果我将Visual Studio Debugger附加到正在运行的进程,则Threads窗口显示7个线程。

我有几个问题:

  • 为什么WinDbg说456个线程和任务管理器说16
  • 为什么任务管理器说有16个线程而Visual Studio Debugger说7
  • !thread命令显示所有这些死线程都没有OSID值。这是否意味着操作系统不再知道它们只是布局的.Net对象?什么是死线?
  • 我应该担心死线数量多吗?

EDIT 2010年2月11日:以下是有关我的应用的更多信息。我们使用后台线程来轮询服务器并执行其他任务。这些任务每隔几分钟执行一次。我们不使用.Net线程池。

编辑2010年2月18日:我在程序中修复了托管的Thread对象泄漏(感谢@highphilosopher)。但是,我对WinDbg,任务管理器和VS调试器为什么不同意线程数量的问题仍然没有答案。谁能解释一下?

编辑2010年3月1日:我仍然有兴趣了解为什么任务管理器和Visual Studio调试器不同意线程数。为什么Visual Studio会过滤一些线程?过滤掉了什么样的线程?

4 个答案:

答案 0 :(得分:11)

任务管理器报告您的流程的总线程数,!threads报告托管线程的数量。如果在WinDbg中使用~命令,您将看到该进程的所有线程线程。

输出中!threads的输出显示了很多死线程。用XXXX列出的用于id的线程是已终止但尚未收集相应线程对象的线程。即报告的数量远远高于实际的线程数。线程计数数字表明456个线程中有449个已经死亡。

我发现线程数量很高,如果应用程序处于空闲状态,那么仍然很奇怪,但是如果没有进一步的信息则很难更具体。

答案 1 :(得分:1)

我的猜测是线程池有重载时段,然后在负载停止时杀死线程。

答案 2 :(得分:1)

您所看到的内容听起来像是在不同的线程上引用了这些线程。由于引用了线程,因此GC无法收集它。线程已完成执行它所发送的方法,因此它既不处于睡眠状态,也不处于可运行状态,因此它必须已经死亡。检查代码中的线程集合或类似的东西。也许是一个被线程迷住但却永远不被解开的事件?

答案 3 :(得分:0)

线程计数不匹配的另一个原因是任务管理器使用非侵入性技术收集信息。调试器通常默认使用入侵附加。

这意味着,任何时候调试运行的Windows应用程序,调试API将远程线程注入目标应用程序并调用KERNEL32!DebugBreak,这是一个int3(0xcc)指令。此时进程中断并停止执行,但是,现在至少有一个额外的调试线程正在运行。