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

发布于 2024-08-20 14:57:52 字数 3612 浏览 4 评论 0原文

当我的 .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 调试器附加到正在运行的进程,“线程”窗口将显示 7 个线程。

我有几个问题:

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

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

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

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

While my .Net 3.5 app was running, the Windows Task Manager shown that my app had 16 threads. I collected a memory dump for the process and opened it using WinDbg/SOS.

Running the !threads command reveals that I have :

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

Here are the first few lines of the !threads output:

       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

If I attach the Visual Studio Debugger to the running process, the Threads windows shows 7 threads.

I have a few questions:

  • Why does WinDbg say there are 456 threads and Task Manager says 16
  • Why does Task Manager say there are 16 threads and Visual Studio Debugger says 7
  • The !thread command shows that all those dead threads don't have a OSID value. Does that mean they are no longer known to the OS are and just .Net objects that are layout around? What is a dead thread exactly?
  • Should I worry about the high number of dead threads?

EDIT Feb 11th 2010: Here is more information about my app. We use background threads to poll the server and perform other tasks. Those tasks are executed every few minutes. We do not use the .Net Thread Pool.

EDIT Feb 18th 2010: I fixed the managed Thread object leak in our program (thanks to @highphilosopher). However, my question about why WinDbg, Task Manager and VS Debugger don't agree on the number of threads is still unanswered. Can anyone explain?

EDIT Mar 1st 2010: I'm still interested in knowing why Task Manager and Visual Studio Debugger don't agree on the number of threads. Why does Visual studio filter some of the threads? What kind of threads does it filter out?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

孤云独去闲 2024-08-27 14:57:52

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

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

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

Task manager reports the total number of threads for your process while !threads reports the number of managed threads. If you use the ~ command in WinDbg you will see all thread threads for the process.

The output from !threads in your output shows a lot of dead threads. The threads listed with XXXX for id are threads that have terminated but the corresponding thread objects have not yet been collected. I.e. the reported number is much higher than the actual number of threads. The thread count numbers state that 449 of the 456 threads are dead.

I find the number of threads high and if the application has been idle it is odd that the're still around, but without further info it is hard to be more specific.

指尖凝香 2024-08-27 14:57:52

我的猜测是线程池有一段时期的重负载,然后在负载消失时杀死线程。

My guess is the thread pool had periods of heavy load and then killed the threads when the load died down.

方圜几里 2024-08-27 14:57:52

您所看到的听起来像是您在不同的线程上引用了这些线程。由于该线程已被引用,因此无法被 GC 收集。该线程已完成执行发送给它的方法,因此它既不处于睡眠状态,也不处于可运行状态,因此它一定是死亡的。检查您的代码中是否有线程集合或类似内容。也许是一个被线程钩住但从未脱钩的事件?

What you're seeing sounds like you have a reference to these threads on a different thread. Since the thread is referenced it can't be Collected by the GC. The thread has completed execution of the method that it was sent to do so it is in neither a sleep state, nor runnable state, so it must be dead. Check your code for a Collection of threads or something similar. Perhaps an event that gets hooked to by the thread, but never unhooked?

我不在是我 2024-08-27 14:57:52

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

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

Another reason why the thread counts will not match is that Task Manager collects information using noninvasive techniques. A debugger usually, and by default uses an invasive attach.

What this means, is that, any time you debug a running windows application, the debug API inject's a remote thread into the target application and call's KERNEL32!DebugBreak, which is an int3 (0xcc) instruction. At this point the process breaks and stop's executing, however, you now have at least one additional debug thread running.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文