幕后的.NET's ThreadPool类

本文探讨了基于Win32 API实现的线程池机制,详细介绍了QueueUserWorkItem等核心函数的功能与运作原理,并分析了.NET中线程池的具体实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

rotor\clr\src\vm\下面,有win32threadpool.hwin32threadpool.cpp两个文件,其头部写着“This module implements Threadpool support using Win32 APIs”,可见池子是用win32 API来实现的。

h文件的头部可以看到一些声明:

 


    
static  BOOL SetMaxThreads(DWORD MaxWorkerThreads, 
                              DWORD MaxIOCompletionThreads);

    
static  BOOL GetMaxThreads(DWORD *  MaxWorkerThreads, 
                              DWORD
*  MaxIOCompletionThreads);
    
    
static  BOOL SetMinThreads(DWORD MinWorkerThreads, 
                              DWORD MinIOCompletionThreads);
    
    
static  BOOL GetMinThreads(DWORD *  MinWorkerThreads, 
                              DWORD
*  MinIOCompletionThreads);
 
    
static  BOOL GetAvailableThreads(DWORD *  AvailableWorkerThreads, 
                                 DWORD
*  AvailableIOCompletionThreads);

    
static  BOOL QueueUserWorkItem(LPTHREAD_START_ROUTINE Function, 
                                  PVOID Context,
                                  ULONG Flags);

 

是不是很眼熟?对,这些就是对应着.NET里相应的函数。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

此块里的文字和图片来自.NET's ThreadPool Class - Behind The Scenes,其中的测试代码大家可以下载试试,很有好处。

作者:Marc Clifton

我本想自己总结来着,但是这老哥总结的很好,借用了。

QueueUserWorkItem

这个方法将工作线程的委托放进一个队列,然后测试是否应该创建一个新的线程。如果需要的话,则会调用CreateWorkerThread方法并且退出。相反的,如果这时候不创建,则另外一个不同的线程,如果不存在的话则会调用CreateThreadGate创建。

ShouldGrowWorkerThread方法测试三个参数来决定是否应该创建一个新线程。

 

 

值得注意的是这个函数首先测试运行的线程数量是否小于可用的CPU数量。很明显这个方法将会返回false当一个或多个运行线程在一个单核机器上运行时。当这个时候,thread gate将被用来稍后创建一个线程。

CreateWorkerThread方法是用来实例化一个实际的工作线程。

 

工作线程将会循环等待直至发生WorkRequestNotification事件,40s之后超时如果事件没有通知。假设事件通知了,会连续将委托从队列里删除(将事件置为未通知状态),检验是否包含的是一个合法的委托,然后调用委托。当委托返回时,工作线程立马检查是否有额外的请求加入队列。如果有,他会处理这些请求;如果没有则返回等待状态。

上述代码暗示:尽快的做你的工作。你的线程所用的任何事件都会导致队列中处理其他请求的延迟。

GateThreadStart

首次方法里会睡眠0.5s。然后他们会去尝试确定是否有一些请求在队列里。如果没有,则回去睡眠。如果有,则调用一个方法去决定时候一个新的线程被创建。此方法创建线程的延迟取决于最后线程创建的时间和当前运行线程的数量。

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

关于是否有两个线程池的问题?

在CreateWorkerThread和CreateCompletionPortThread两个方法里,都调用了CreateUnimpersonatedThread这个方法来创建新线程。

其最终都是用的WIN32 API的CreateThread来创建线程,所以两种线程的来源是一样的;是不是能算的上两个线程池,逻辑上可以算做是两个吧,可能是因为为了分别响应工作线程和IO完成端口线程,所以多了区分。如果真是两个池的话,为什么不将两种线程用两套API分开呢,还非封装在一个类里?

而且工作线程和IO完成端口线程有个区别就是:后者需要和IO端口进行绑定,并且一直等待至IO请求执行返回。(此点我也了解的不是甚清楚,欢迎了解的同学补充)。

 

不早了,洗洗睡。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值