本文主要结合四个应用场景介绍Windows内置的几种线程池机制,并配了一张思维导图。事实上,Jeffrey在该书中,并没有过深的去探讨“线程池”的机制,Windows所提供的这四种线程池机制也并非所有场景都合适,后续我将会单独开一篇博客来自己实现一个线程池。
如上图,本文主要介绍这四个线程池应用场景。
一、异步函数调用
它的流程大致分为三步,参考batch.exe示例。
1)定义回调例程——TaskHandler;
2)创建工作项。
// Create the work item that will be used by all tasks
g_pWorkItem = CreateThreadpoolWork(TaskHandler, NULL, NULL);
// Submit 4 tasks by using the same work item
SubmitThreadpoolWork(g_pWorkItem);
SubmitThreadpoolWork(g_pWorkItem);
SubmitThreadpoolWork(g_pWorkItem);
SubmitThreadpoolWork(g_pWorkItem);
二、定时器
Jeffrey介绍的第二种应用场景,实际上就是定时器。我们可以直接用“waitable timer”,也可以用该章介绍的便利函数。事实上,QT的Timer封装的更好,使用起来更方便。
参照TimedMsgBox.exe示例,它的流程如下:
1)定义回调例程——MsgBoxTimeoutCallback。
2)创建Timer
// Create the threadpool timer object
PTP_TIMER lpTimer =
CreateThreadpoolTimer(MsgBoxTimeoutCallback, NULL, NULL);
// Start the timer in one second to trigger every 1 second
ULARGE_INTEGER ulRelativeStartTime;
ulRelativeStartTime.QuadPart = (LONGLONG) -(10000000); // start in 1 second
FILETIME ftRelativeStartTime;
ftRelativeStartTime.dwHighDateTime = ulRelativeStartTime.HighPart;
ftRelativeStartTime.dwLowDateTime = ulRelativeStartTime.LowPart;
SetThreadpoolTimer(
lpTimer,
&ftRelativeStartTime,
1000, // Triggers every 1000 milliseconds
0
);
三、内核触发
“等待某个内核对象触发,然后执行异步调用”,相对前面两题,这是更一般意义的机制。它的步骤如下:
1)定义回调例程;
2) 创建线程池等待对象;
PTP_WAIT CreateThreadpoolWait(
PTP_WAIT_CALLBACK pfnWaitCallback,
PVOID pvContext,
PTP_CALLBACK_ENVIRON pcbe);
VOID SetThreadpoolWait(
PTP_WAIT pWaitItem,
HANDLE hObjcet,
PFILETIME pftTimeout);
四、异步IO完成通知
最后一种常见是等待异步IO完成通知,然后调用异步执行函数。步骤如下:
1)定义回调函数,包含重叠结构。
2)创建一个线程池IO对象
PTP_WAIT CreateThreadpoolIo(
HANDLE hDevice,
PTP_WIN32_IO_CALLBACK pfnWaitCallback,
PVOID pvContext,
PTP_CALLBACK_ENVIRON pcbe);
3)关联设备对象和线程池IO对象
VOID StartThreadpoolIo(PTP_IO pio);