此堆栈跟踪是不是以 _NtWaitForSingleObject@12() 结尾,表示线程阻塞或空闲?

Posted

技术标签:

【中文标题】此堆栈跟踪是不是以 _NtWaitForSingleObject@12() 结尾,表示线程阻塞或空闲?【英文标题】:Is this stack trace ending with _NtWaitForSingleObject@12() indicating a blocked or an idle thread?此堆栈跟踪是否以 _NtWaitForSingleObject@12() 结尾,表示线程阻塞或空闲? 【发布时间】:2015-12-14 15:48:30 【问题描述】:

我有一个大量使用任务并行库的应用程序。当我的应用程序运行时,我注意到 ProcessExplorer 报告的我的应用程序使用的线程数有时超过 200 个线程,最终应用程序在线程用完时会锁定。

当我使用 AdPlus 对内存进行 FULL DUMP 并在 Visual Studio 中打开它时,我看到当时有 82 个线程在运行(尽管当时 ProcessExplorer 报告超过 100 个)。

其中许多线程(其中 42 个)仅显示以下堆栈跟踪:

ntdll.dll!_NtWaitForSingleObject@12()  + 0x15 bytes 
ntdll.dll!_NtWaitForSingleObject@12()  + 0x15 bytes 
kernel32.dll!@BaseThreadInitThunk@12()  + 0x12 bytes    
ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes   
ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes    

我的问题是:

具有上述堆栈跟踪的线程是否等待我启动并随后成为孤立的东西? 或者该堆栈跟踪是否仅表示一个空闲线程?

【问题讨论】:

堆栈跟踪表明一个线程正在等待某个内核对象。孤立的内核对象将打破等待条件,因此这是在等待一个活动对象。处于等待状态的线程与空闲线程同义。 为什么这是一个与your other one 不同的问题? 因为它们是两个独立的问题。这个问题是,上面的堆栈跟踪是否表明一个线程在我的工作中被阻塞,或者只是一个空闲线程可用于工作。另一个问题是帮助我理解为什么堆栈跟踪没有指示我的托管代码中的起点。 @IInspectable 那么上面是在等待内核对象吗?我怎样才能弄清楚它在等待什么对象?那么这个线程在等待时对 TPL 可用,还是在等待满足之前不可用? 您正在查看的线程很可能是等待更多工作的线程池线程,或者等待调度程序允许它们启动的任务。顺便说一句,WinDbg 可以比 VS 更深入地挖掘内存转储。 (它只是有一个陡峭的学习曲线) 【参考方案1】:

所以事实证明,WinDbg 确实是获得所有这些线程在做什么的问题的明确答案的最佳方式。

正如 B 所说,'_NtWaitForSingleObject@12 表示线程要么空闲等待工作,要么等待调度器'

使用WinDbg中的!threadpool命令,下面的内容清楚地表明这些线程必须归线程池所有,并且它们确实是空闲的:

0:073> !threadpool
CPU utilization: 21%
Worker Thread: Total: 256 Running: 2 Idle: 254 MaxLimit: 1023 MinLimit: 256
Work Request in Queue: 0
--------------------------------------
Number of Timers: 1
--------------------------------------
Completion Port Thread:Total: 1 Free: 1 MaxFree: 4 CurrentLimit: 1 MaxLimit: 1000 MinLimit: 256

【讨论】:

以上是关于此堆栈跟踪是不是以 _NtWaitForSingleObject@12() 结尾,表示线程阻塞或空闲?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Processing debugger中获取堆栈跟踪

Node.JS + TypeScript如何从堆栈跟踪中跟踪源代码?

通过 syslog 发送 log4j2 堆栈跟踪

使用windows api堆栈跟踪另一个进程c

.NET 发布模式构建中是不是提供堆栈跟踪信息?

Laravel:是不是可以在捕获异常时记录堆栈跟踪并继续执行?