线程池
目的:减少创建与撤销线程以及切换的额外开销,
简单实现分析:首先创建一个信标对象hSemaphore(初始化:可以容纳最多的作业数max,当前资源数为0)。然后创建一定数量的工作线程(WorkThread),比如10个线程,这些线程都在循环中WaitForSingleObject(hSemaphore)。由于一开始信标的当前资源数是0,所以信标是unsigned,那么所有线程都处于等待状态。另创建一个任务队列(queue)以及一个工作项目添加函数(例如叫做AddWork(pfnWorkfun, pParam)),每当有新的任务要添加,都执行AddWork,在AddWork内部将pfnWorkfun和pParam配对的加入到任务队列的尾部(例如可以创建一个结构体等等),并调用ReleaseSemaphore使当前资源数增加1。当信标的当前资源数大于1的时候,会发出信号,所有等待的工作线程之一会获得执行。该工作线程pop出队列的第一项,然后在内部调用你的pfnWorkfun来完成具体的操作,最后对信标当前资源数量减1。直到信标当前资源数为0为止。(完全没有考虑线程的同步,以及动态增减待命工作线程等问题,具体实现时要注意)
但是,系统已经提供了一个非常简单的使用线程池的方法,只需要调用一个函数即可(QueueUserWorkItem)。调用该函数并传入例如(2)中所指定的pfnWorkfun以及pParam,系统便自动将此配对工作加入到线程池的工作队列中排队,当系统的线程池中有空闲的线程时就依次取出WorkItem并加以执行。这就是所谓的异步调用函数(Call Functions Asynchronously)。
BOOL QueueUserWorkItem(
PTHREAD_START_ROUTINE pfnCallback,
PVOID pvContext,
ULONG dwFlags);
函数原型:DWORD WINAPI WorkItemFunc(PVOID pvContext);
1.异步方法调用
异步方法调用有以下两种方法:
(1)线程函数原型(回调函数)
VOID NTAPI SimpleCallback(
PTP_CALLBACK_INSTANCE pInstance,
PVOID pvContext );
TrySubmitThreadpoolCallback 该函数将线程函数执行请求发到线程池,并将一个"工作项目"添加到线程池的队列中。注:我们不需要调用CreateThread函数,线程池中的线程会执行我们的回调函数
(2)显示控制"工作项目"
CreateThreadpoolWork 创建一个工作项目
SubmitThreadpoolWork 将工作项目提交到线程池中,一个工作项目可以多次提交到线程池中。
WaitForThreadpoolWorkCallbacks 等待线程函数执行完毕或取消执行线程函数。
CreateThreadpoolWork要求的线程函数原型:
VOID CALLBACK WorkCallback(
PTP_CALLBACK_INSTANCE Instance,
PVOID Context,
PTP_WORK Work);
VOID WaitForThreadpoolWorkCallbacks(
PTP_WORK pWork,
BOOL bCancelPendingCallbacks );
2.时间间隔内调用函数
(1)CreateThreadpoolTimer要求的线程函数原型
VOID CALLBACK TimeoutCallback (
PTP_CALLBACK_INSTANCE pInstance, // See "Callback Termination Actions" section
PVOID pvContext,
PTP_TIMER pTimer );
(2)步骤
CreateThreadpoolTimer
SetThreadpoolTimer
WaitForThreadpoolTimerCallbacks
CloseThreadpoolTimer
3.当内核对象处于Signal状态时调用函数
当指定的内核对象变成Signal状态或等待超时,线程池会用户指定的线程函数。之后当内核对象再次变成Signal状态时,线程函数不会被调用,除非再次调用SetThreadpoolWait注册线程函数。
(1)CreateThreadpoolWait要求的线程函数原型
VOID CALLBACK WaitCallback (
PTP_CALLBACK_INSTANCE pInstance, // See "Callback Termination Actions" section
PVOID Context,
PTP_WAIT Wait,
TP_WAIT_RESULT WaitResult );
CreateThreadpoolWait
SetThreadpoolWait 不允许多次注册同样的Handle,但是我们可以用DuplicateHandle函数复制一个句柄 然后再注册。
WaitForThreadpoolWaitCallbacks
CloseThreadpoolWait
4.当异步I/O请求结束后调用函数
5.回调终结后的操作和私有线程
天行健,君子当自强不息

浙公网安备 33010602011771号