现在的位置: 首页 > 综合 > 正文

.NET常见线程简介

2013年08月17日 ⁄ 综合 ⁄ 共 7386字 ⁄ 字号 评论关闭

原文地址:http://blogs.msdn.com/tess/archive/2005/12/20/505862.aspx

 

当你分析一个dump文件的时候,调试里面最艺术的地方就是知道哪些东西是可以忽略的,而哪些是你想要的东西。

 

特别是在你分析一个程序停止响应(hang)的bug时,了解这些常见线程对你非常有帮助,浏览线程各堆栈列表的时候,你可以知道不是这个线程出问题了,也不是那个线程…………

 

因为大部分时间我是跟asp.net打交道,所以我将通过分析w3wp.exeIIS 6里面用来执行asp.net页面代码的进程)的一个dump文件来介绍这些常见线程。所有这些常见线程都有一个共性,就是它们要么是睡眠状态(sleeping state)或者等待状态(waiting state),等待处理更多的工作。因此虽然它们看起来是造成程序停止响应(hang)的原因,实际上它们并不是真正的罪魁祸首……如果你发现它们处于其他的状态,比如说正在执行某个任务,那么它们就需要得到更多的关注了。

 

我把这些常见的线程划分为以下几个种类:

1.         CLR线程

2.         W3WP线程

3.         RPC线程

4.         其他COM线程

 

CLR线程

线程池(ThreadPool)管理程序有五种主要的线程类型:

 

1.         Completion Port/IO 线程和工作(Worker)线程是执行你的托管(managed)代码和.net代码的线程。

2.         一个闸门(gate)线程根据CPU的利用率,GC的频率和工作队列(worker queue)的大小,动态地创建或销毁工作线程和IO线程。

3.         停滞(wait)线程,用来等待一些同步对象触发的事件,比如说,一个程序员使用WaitHandle类(或它的派生类),这个类内部使用WaitForSingleObject Win32 API函数来是这个线程处于停滞状态。

4.         最后第五个是定时器(Timer)线程,它是用来调用定时器(Timer)回调函数的线程。

 

下面的列表列出了.NET 1.1中它们在停滞状态时候的模样(由于我在翻译的时候,机器上没有微软.NET 2.0的公开符号文件,所以只好原文拷贝下来了,有机会我会将2.0里面的堆栈列出来):

 

闲置状态中的CLR工作线程(Worker Thread):

  11  Id: fb8.268 Suspend: 0 Teb: 7ffaa000 Unfrozen
ChildEBP RetAddr  Args to Child              
0199fdf8 7c822124 77e6baa8 00000234 00000000 ntdll!KiFastSystemCallRet
0199fdfc 77e6baa8 00000234 00000000 0199fe40 ntdll!NtWaitForSingleObject+0xc
0199fe6c 77e6ba12 00000234 00009c40 00000000 kernel32!WaitForSingleObjectEx+0xac
0199fe80 791d401f 00000234 00009c40 00000000 kernel32!WaitForSingleObject+0x12
0199fea4 791fdacc 00000000 00000000 80a56bcc mscorsvr!ThreadpoolMgr::WorkerThreadStart+0x3a
0199ffb8 77e66063 000b6da8 00000000 00000000 mscorsvr!ThreadpoolMgr::intermediateThreadProc+0x44
0199ffec 00000000 791fda8b 000b6da8 00000000 kernel32!BaseThreadStart+0x34

 

闲置状态中的CLR Completion Port/IO Thread

   9  Id: fb8.ef8 Suspend: 0 Teb: 7ffac000 Unfrozen
ChildEBP RetAddr  Args to Child              
0191fec0 7c821bf4 77e6611a 0000023c 0191ff1c ntdll!KiFastSystemCallRet
0191fec4 77e6611a 0000023c 0191ff1c 0191ff08 ntdll!NtRemoveIoCompletion+0xc
0191fef0 791fdb22 0000023c 0191ff18 0191ff1c kernel32!GetQueuedCompletionStatus+0x29
0191ff24 791fdacc 00000001 809a05fe 7ffac000 mscorsvr!ThreadpoolMgr::CompletionPortThreadStart+0x49
0191ffb8 77e66063 000b6da8 00000000 00000000 mscorsvr!ThreadpoolMgr::intermediateThreadProc+0x44
0191ffec 00000000 791fda8b 000b6da8 00000000 kernel32!BaseThreadStart+0x34
 

 

闲置状态中的CLR 闸门(gate)线程:

  10  Id: fb8.bdc Suspend: 0 Teb: 7ffab000 Unfrozen
ChildEBP RetAddr  Args to Child              
0195fe50 7c821364 77e42439 00000000 0195fe94 ntdll!KiFastSystemCallRet
0195fe54 77e42439 00000000 0195fe94 00000000 ntdll!NtDelayExecution+0xc
0195febc 77e424b7 000001f4 00000000 0195ffb8 kernel32!SleepEx+0x68
0195fecc 791bf4f9 000001f4 0b2646e6 00000939 kernel32!Sleep+0xf
0195ffb8 77e66063 00000000 00000000 00000000 mscorsvr!ThreadpoolMgr::GateThreadStart+0x54
0195ffec 00000000 791bf4a5 00000000 00000000 kernel32!BaseThreadStart+0x34

 

闲置状态中的CLR停滞(wait)线程:

  25  Id: 230.ac0 Suspend: 0 Teb: 7ff4c000 Unfrozen
ChildEBP RetAddr  Args to Child              
1b88ff6c 7c573a4e 00000001 1b88ff84 00000000 NTDLL!ZwDelayExecution+0xb 
1b88ff8c 7923558c ffffffff 00000001 198ba828 KERNEL32!SleepEx+0x32 
1b88ffb4 7c57438b 00000000 198ba828 197f7498 mscorsvr!ThreadpoolMgr::WaitThreadStart+0x45 
1b88ffec 00000000 7923556a 1973b3d0 00000000 KERNEL32!BaseThreadStart+0x52

 

闲置状态中的CLR定时器(Timer)线程:

  18  Id: fb8.914 Suspend: 0 Teb: 7ff5f000 Unfrozen
ChildEBP RetAddr  Args to Child              
0224ff38 7c821364 77e42439 00000001 0224ff7c ntdll!KiFastSystemCallRet
0224ff3c 77e42439 00000001 0224ff7c 000003e8 ntdll!NtDelayExecution+0xc
0224ffa4 791cc578 000003e8 00000001 00000000 kernel32!SleepEx+0x68
0224ffb8 77e66063 00000000 00000000 00000000 mscorsvr!ThreadpoolMgr::TimerThreadStart+0x30
0224ffec 00000000 791cc548 00000000 00000000 kernel32!BaseThreadStart+0x34

 

除了这些线程,CLR还创建了一些其他的线程:

 

在一个多核主机上,在一个CLR宿主进程中(服务器版本的GC),每一个处理器都会由一个垃圾回收(GC)线程,而在超线程系统上,每个进程会有两个。这些线程用来处理托管堆上的垃圾回收操作。

 

另外在每一个进程里我们还有终结器线程(Finalizer Thread),这个线程运行所有的Finalize函数。在调试进程无响应(hang)和高内存使用率的情形时,要特别注意这个线程。如果在收集一个对象(finalizing an object)的时候它被其他的东西阻塞(blocked in any way)的话,那么你的托管变量就不能被以合适的方式清理掉,最终你就得到一个内存泄漏的结果,并且/或者有一个高CPU使用率的情形,因为 GC将不得不重复启动以保证你的内存可用率。

 

最后,CLR还提供了一个DebuggerThread用来提供托管程序调试服务。

 

闲置状态中的CLR垃圾回收(GC)线程:

  13  Id: fb8.c10 Suspend: 0 Teb: 7ffa8000 Unfrozen
ChildEBP RetAddr  Args to Child              
01d6fefc 7c822124 77e6baa8 000002b4 00000000 ntdll!KiFastSystemCallRet
01d6ff00 77e6baa8 000002b4 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
01d6ff70 77e6ba12 000002b4 ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xac
01d6ff84 791fe6b0 000002b4 ffffffff 00000000 kernel32!WaitForSingleObject+0x12
01d6ffac 792356be 00000000 01d6ffec 77e66063 mscorsvr!gc_heap::gc_thread_function+0x2f
01d6ffb8 77e66063 000d2ed8 00000000 00000000 mscorsvr!gc_heap::gc_thread_stub+0x1e
01d6ffec 00000000 792356a0 000d2ed8 00000000 kernel32!BaseThreadStart+0x34

 

闲置状态中的CLR终结器(Finalizer)线程:

  17  Id: fb8.7b0 Suspend: 0 Teb: 7ffa4000 Unfrozen
ChildEBP RetAddr  Args to Child              
01e6fdf8 7c822114 77e6711b 00000002 01e6fe48 ntdll!KiFastSystemCallRet
01e6fdfc 77e6711b 00000002 01e6fe48 00000001 ntdll!NtWaitForMultipleObjects+0xc
01e6fea4 77e61075 00000002 793eee08 00000000 kernel32!WaitForMultipleObjectsEx+0x11a
01e6fec0 7927826b 00000002 793eee08 00000000 kernel32!WaitForMultipleObjects+0x18
01e6fee0 791fecf4 000002dc 00000000 792376a4 mscorsvr!WaitForFinalizerEvent+0x5a
01e6ff24 79245681 00000000 809a05fe 7ffa4000 mscorsvr!GCHeap::FinalizerThreadStart+0x96
01e6ffb8 77e66063 000d5500 00000000 00000000 mscorsvr!Thread::intermediateThreadProc+0x44
01e6ffec 00000000 79245640 000d5500 00000000 kernel32!BaseThreadStart+0x34

 

闲置状态中的CLR调试(Debugger)线程:

   12  Id: fb8.b30 Suspend: 0 Teb: 7ffa9000 Unfrozen
ChildEBP RetAddr  Args to Child              
01adfe70 7c822114 77e6711b 00000003 01adfec0 ntdll!KiFastSystemCallRet
01adfe74 77e6711b 00000003 01adfec0 00000001 ntdll!NtWaitForMultipleObjects+0xc
01adff1c 77e61075 00000003 01adff5c 00000000 kernel32!WaitForMultipleObjectsEx+0x11a
01adff38 79238fd6 00000003 01adff5c 00000000 kernel32!WaitForMultipleObjects+0x18
01adffa0 79238f4d 00000000 00000000 00000000 mscorsvr!DebuggerRCThread::MainLoop+0x90
01adffb0 7923a714 01adffec 77e66063 019d1eb0 mscorsvr!DebuggerRCThread::ThreadProc+0x68
01adffb8 77e66063 019d1eb0 00000000 00000000 mscorsvr!DebuggerRCThread::ThreadProcStatic+0xb
01adffec 00000000 7923a709 019d1eb0 00000000 kernel32!BaseThreadStart+0x34

 

W3WP线程

W3WP进程里面主要有主线程、线程池线程和压缩线程。

 

主线程负责启动和关闭进程,线程池线程用来处理页面请求,而压缩线程就如名字如表明的那样是用来处理压缩数据的。

 

W3WP主(main)线程:

.  0  Id: fb8.fd8 Suspend: 0 Teb: 7ffdf000 Unfrozen
ChildEBP RetAddr  Args to Child              
0006fc08 7c822124 77e6baa8 00000184 00000000 ntdll!KiFastSystemCallRet
0006fc0c 77e6baa8 00000184 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
0006fc7c 77e6ba12 00000184 ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xac
0006fc90 5a36467a 00000184 ffffffff 00000000 kernel32!WaitForSingleObject+0x12
0006fca0 5a366e63 00254ff8 5a3af41d 00000000 w3dt!WP_CONTEXT::RunMainThreadLoop+0x10
0006fca8 5a3af41d 00000000 64711da9 00000000 w3dt!UlAtqStartListen+0x2d
0006fcb8 5a3bc259 0100141c 010013e4 010012d0 w3core!W3_SERVER::StartListen+0xbd
0006ff0c 0100187c 00000007 002538e0 00000000 w3core!UlW3Start+0x26e
0006ff44 01001a23 00000007 002538e0 002543d0 w3wp!wmain+0x22a
0006ffc0 77e523cd 00000000 00000000 7ffd7000 w3wp!wmainCRTStartup+0x12b
0006fff0 00000000 010018f8 00000000 78746341 kernel32!BaseProcessStart+0x23

 

闲置状态中的w3wp线程池(ThreadPool)线程:

   2  Id: fb8.c5c Suspend: 0 Teb: 7ffd9000 Unfrozen
ChildEBP RetAddr  Args to Child              
00c8ff24 7c821bf4 77e6611a 00000170 00c8ff80 ntdll!KiFastSystemCallRet
00c8ff28 77e6611a 00000170 00c8ff80 00c8ff6c ntdll!NtRemoveIoCompletion+0xc
00c8ff54 5a30249e 00000170 00c8ff7c 00c8ff80 kernel32!GetQueuedCompletionStatus+0x29
00c8ff8c 5a3026bc 00000000 00258580 5a300000 w3tp!THREAD_POOL_DATA::ThreadPoolThread+0x33
00c8ffa0 5a301db9 00000102 00000000 00000000 w3tp!THREAD

抱歉!评论已关闭.