Win32编程之线程池(十二)
一、线程池概念介绍
1.线程的执行流程

2.线程池原理

二、线程池异步函数的调用
1.TrySubmitThreadpoolCallback函数
TrySubmitThreadpoolCallback 函数是Windows操作系统提供的一个函数,它用于将回调函数提交到线程池中以异步执行。线程池是一组可用于执行并发任务的线程,它可以帮助提高程序的性能和资源利用率。
函数原型:
BOOL TrySubmitThreadpoolCallback( PTP_SIMPLE_CALLBACK pfns, PVOID pv, PTP_CALLBACK_ENVIRON pcbe );
参数说明:
pfns:一个指向回调函数的指针,该函数将在线程池中的工作线程上执行。pv:传递给回调函数的用户数据指针。pcbe:一个可选的线程池回调环境,可以用来配置线程池行为。
返回值:
- 如果成功提交回调函数,函数返回非零值。
- 如果线程池队列已满,或者出现其他错误,函数返回零。
使用方法:
(1).首先,需要初始化线程池回调环境(TP_CALLBACK_ENVIRON)。这可以通过使用 InitializeThreadpoolEnvironment 函数来完成,以确保线程池的配置符合你的需求。
TP_CALLBACK_ENVIRON callbackEnviron; InitializeThreadpoolEnvironment(&callbackEnviron);
(2).创建回调函数。回调函数的原型应与 TP_SIMPLE_CALLBACK 一致,通常如下:
VOID CALLBACK MyCallback(PTP_CALLBACK_INSTANCE instance, PVOID context)
{
// 在这里执行你的异步任务
}
(3).使用 TrySubmitThreadpoolCallback 函数提交回调函数到线程池,以异步执行任务:
BOOL submitted = TrySubmitThreadpoolCallback(MyCallback, userData, &callbackEnviron);
if (submitted) {
// 成功提交任务到线程池
} else {
// 无法提交任务,处理错误
}
当任务完成后,线程池将调用回调函数,执行你的异步任务。在回调函数中,你可以访问传递的用户数据 (userData) 并执行所需的操作。
最后,不要忘记清理线程池回调环境(如果有必要):
DestroyThreadpoolEnvironment(&callbackEnviron);
TrySubmitThreadpoolCallback 函数通常用于异步执行工作,以充分利用系统的多核处理能力。它允许你将工作提交给线程池,而无需自行创建和管理线程。但缺点是每次都需要提交创建新的工作项,每一次创建都会浪费一定的内存而且会损失一定的效率;请确保在使用线程池时小心处理错误情况,并在适当的地方清理资源。
示例代码:
#include <Windows.h>
#include <stdio.h>
VOID CALLBACK ThreadpoolCallback(PTP_CALLBACK_INSTANCE instance, PVOID context) {
// 在这里执行你的异步任务
printf("%s\n", (char*)context);
}
int main() {
TP_CALLBACK_ENVIRON callbackEnviron;
InitializeThreadpoolEnvironment(&callbackEnviron);
char str[] = "Hello world";
BOOL submitted = TrySubmitThreadpoolCallback(ThreadpoolCallback, str, &callbackEnviron);
if (submitted) {
printf("执行成功\n");
}
DestroyThreadpoolEnvironment(&callbackEnviron);
return 1;
}
2.CreateThreadpoolWork函数
CreateThreadpoolWork 函数是 Windows 操作系统提供的函数,用于创建线程池工作对象,这些对象可用于将工作项提交到线程池中执行。线程池工作对象代表一个可执行的工作项,该工作项通常由线程池中的工作线程执行。
函数原型:
PTP_WORK CreateThreadpoolWork( PTP_WORK_CALLBACK pfnwk, PVOID pv, PTP_CALLBACK_ENVIRON pcbe );
参数说明:
pfnwk:一个指向工作项回调函数的指针,该函数将在线程池中的工作线程上执行。pv:传递给工作项回调函数的用户数据指针。pcbe:一个可选的线程池回调环境,用于配置工作项的行为。
返回值:
- 如果成功创建工作项对象,函数返回一个指向
TP_WORK结构的指针(PTP_WORK类型)。 - 如果出现错误,函数返回 NULL。
使用方法:
首先,需要初始化线程池回调环境(TP_CALLBACK_ENVIRON)。这可以通过使用 InitializeThreadpoolEnvironment 函数来完成,以确保线程池的配置符合你的需求。
TP_CALLBACK_ENVIRON callbackEnviron; InitializeThreadpoolEnvironment(&callbackEnviron);
创建工作项回调函数。回调函数的原型应与 PTP_WORK_CALLBACK 一致,通常如下:
VOID CALLBACK MyWorkCallback(PTP_CALLBACK_INSTANCE instance, PVOID context, PTP_WORK work)
{
// 在这里执行你的工作项任务
}
使用 CreateThreadpoolWork 函数创建工作项对象,并将其绑定到回调函数:
PTP_WORK workItem = CreateThreadpoolWork(MyWorkCallback, userData, &callbackEnviron);
if (workItem == NULL) {
// 处理工作项创建失败的错误
}
使用 SubmitThreadpoolWork 函数将工作项提交到线程池,以异步执行任务:
SubmitThreadpoolWork(workItem);
当线程池中的工作线程可用时,它们将调用回调函数 MyWorkCallback 来执行工作项任务。在回调函数中,你可以访问传递的用户数据 (userData) 并执行所需的操作。在工作项完成后,你可以通过调用 CloseThreadpoolWork 函数来关闭工作项对象,并在不再需要时释放资源:
CloseThreadpoolWork(workItem);
CreateThreadpoolWork 和相关的线程池函数通常用于异步执行工作,以提高程序性能并充分利用系统的多核处理能力。线程池可以自动管理线程的创建和销毁,使得线程管理更加高效。确保适时关闭和释放线程池工作项以防止资源泄漏。
示例代码:
#include <Windows.h>
#include <stdio.h>
VOID CALLBACK ThreadpoolWork(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work) {
printf("%s\n", (char*)Context);
}
int main() {
char str[] = "hello world";
PTP_WORK workitem = CreateThreadpoolWork(ThreadpoolWork, str, NULL);
if (workitem == NULL) {
printf("CreateThreadpoolWork Failed!\n");
return 0;
}
SubmitThreadpoolWork(workitem);
SubmitThreadpoolWork(workitem);
SubmitThreadpoolWork(workitem);
SubmitThreadpoolWork(workitem);
CloseThreadpoolWork(workitem);
return 1;
}
三、线程池的周期性调用
1.CreateThreadpoolTimer()函数
CreateThreadpoolTimer 函数是 Windows API 中的一个函数,用于创建一个线程池定时器对象。线程池定时器可用于在指定时间间隔后执行回调函数。这有助于避免创建单独的线程来执行定时任务,提高了性能和资源利用率。
函数原型:
PTP_TIMER CreateThreadpoolTimer( PTP_TIMER_CALLBACK pfn, PVOID pv, PTP_CALLBACK_ENVIRON pcbe );
参数解释:
pfn:指向定时器回调函数的指针。该回调函数将在定时器到期时被调用。pv:可选参数,指向传递给回调函数的上下文数据的指针。pcbe:可选参数,指向线程池回调环境的指针,可用于自定义线程池行为。可以传递NULL。
返回值:
如果函数调用成功,将返回指向新创建的线程池定时器对象的指针(PTP_TIMER)。如果函数调用失败,将返回 NULL,您可以通过调用 GetLastError 获取错误信息。
2.SetThreadpoolTimer函数
SetThreadpoolTimer 函数是 Windows API 中用于更改线程池定时器的触发时间和间隔的函数。线程池定时器是一种高效的机制,可用于在指定时间间隔后执行回调函数。
函数原型:
VOID SetThreadpoolTimer( PTP_TIMER pti, PFILETIME pftDueTime, DWORD msPeriod, DWORD msWindowLength );
参数解释:
pti:指向线程池定时器的指针,通过CreateThreadpoolTimer函数创建。pftDueTime:指向FILETIME结构的指针,用于指定定时器的下一次触发时间。可以为NULL,表示立即触发。msPeriod:定时器的触发周期,以毫秒为单位。如果设置为0,则定时器将变为单次触发,不会重复。msWindowLength:可选参数,指定触发时间的窗口长度(在msPeriod基础上),用于控制定时器的灵活性。可以设置为0。该参数为参数三的周期性提供一个随机延迟时间值,能够避免多计时器同频回调冲突,也能避免多定时器相近时段上下文切换。
3.CloseThreadpoolTimer函数
CloseThreadpoolTimer 函数是 Windows API 中用于关闭线程池定时器的函数。线程池定时器是一种高效的机制,可用于在指定时间间隔后执行回调函数。在不再需要定时器时,应使用 CloseThreadpoolTimer 函数来释放相关资源。
函数原型:
VOID CloseThreadpoolTimer( PTP_TIMER ptimer );
参数解释:
ptimer:指向要关闭的线程池定时器的指针,通过CreateThreadpoolTimer函数创建。
示例代码:
#include <Windows.h>
#include <stdio.h>
VOID NTAPI PoolTimerProc(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_TIMER Timer) {
printf("Hello World\n");
}
int main() {
PTP_TIMER lpTimer = CreateThreadpoolTimer(PoolTimerProc, NULL, NULL);
FILETIME dueTime;
GetSystemTimeAsFileTime(&dueTime);
SetThreadpoolTimer(lpTimer, &dueTime, 1000, 0);
system("pause");
CloseThreadpoolTimer(lpTimer);
return 1;
}
四、线程池内核对象触发调用
1.CreateThreadpoolWait函数
CreateThreadpoolWait 函数是 Windows API 中用于创建线程池等待对象的函数。线程池等待对象用于等待一个或多个事件或状态的发生,并在事件发生时执行指定的回调函数。这是一种有效的机制,用于异步事件处理。
函数原型:
PTP_WAIT CreateThreadpoolWait( PTP_WAIT_CALLBACK pfnwaithint, PVOID pv, PTP_CALLBACK_ENVIRON pcbe );
参数解释:
pfnwaithint:指向等待回调函数的指针,当等待对象的状态发生变化时,将调用此回调函数。pv:可选参数,指向传递给回调函数的上下文数据的指针。pcbe:可选参数,指向线程池回调环境的指针,可用于自定义线程池行为。可以传递NULL。
返回值:
如果函数调用成功,将返回指向新创建的线程池等待对象的指针(PTP_WAIT)。如果函数调用失败,将返回 NULL,您可以通过调用 GetLastError 获取错误信息。
2.SetThreadpoolWait函数
SetThreadpoolWait 函数是 Windows API 中用于配置线程池等待对象的函数。线程池等待对象用于等待一个或多个事件或状态的发生,并在事件发生时执行指定的回调函数。使用 SetThreadpoolWait 函数,您可以将等待对象与事件或状态关联,并设置回调函数。
函数原型:
VOID SetThreadpoolWait( PTP_WAIT pwa, HANDLE h, PFILETIME pftTimeout, );
参数解释:
pwa:指向线程池等待对象的指针,通过CreateThreadpoolWait函数创建。h:要等待的事件句柄。可以是事件、互斥体等内核对象的句柄。pftTimeout:可选参数,指向FILETIME结构的指针,用于设置等待的超时时间。如果不希望设置超时时间,可以传递NULL。
3. CloseThreadpoolWait函数
CloseThreadpoolWait 函数是 Windows API 中用于关闭线程池等待对象的函数。线程池等待对象用于等待一个或多个事件或状态的发生,并在事件发生时执行指定的回调函数。当不再需要等待对象时,应使用 CloseThreadpoolWait 函数来释放相关资源。
函数原型:
VOID CloseThreadpoolWait( PTP_WAIT pwa );
参数解释:
pwa:指向要关闭的线程池等待对象的指针,通过CreateThreadpoolWait函数创建。
示例代码:
#include <Windows.h>
#include <iostream>
// 等待回调函数
VOID CALLBACK WaitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context, PTP_WAIT wait, TP_WAIT_RESULT waitResult) {
printf("Hello World\n");
}
int main() {
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//超时时间设置为NULL,表示一直等待下去
PTP_WAIT pWait = CreateThreadpoolWait(WaitCallback, NULL, NULL);
//立即执行
ULARGE_INTEGER ulRelativeStartTime;
ulRelativeStartTime.QuadPart = 0;
FILETIME ftRelativeStartTime;
ftRelativeStartTime.dwHighDateTime = ulRelativeStartTime.HighPart;
ftRelativeStartTime.dwLowDateTime = ulRelativeStartTime.LowPart;
SetThreadpoolWait(pWait, hEvent, &ftRelativeStartTime);
//等候五秒再触发
/*ULARGE_INTEGER ulRelativeStartTime;
ulRelativeStartTime.QuadPart = (LONGLONG)-(50000000);
FILETIME ftRelativeStartTime;
ftRelativeStartTime.dwHighDateTime = ulRelativeStartTime.HighPart;
ftRelativeStartTime.dwLowDateTime = ulRelativeStartTime.LowPart;
SetThreadpoolWait(pWait, hEvent, &ftRelativeStartTime);*/
//超时时间为NULL,表示一直等待下去,直到事件触发
//SetThreadpoolWait(pWait, hEvent, NULL);
getchar();
SetEvent(hEvent);
getchar();
CloseThreadpoolWait(pWait);
return 0;
}
五、线程池IO完成调用
1.CreateThreadpoolIo函数
CreateThreadpoolIo 函数是 Windows API 中用于创建线程池 I/O 对象的函数。线程池 I/O 对象可用于异步 I/O 操作的管理,以提高性能和资源利用率。
函数原型:
PTP_IO CreateThreadpoolIo( HANDLE fl, PTP_WIN32_IO_CALLBACK pfnio, PVOID pv, PTP_CALLBACK_ENVIRON pcbe );
参数解释:
fl:要与线程池 I/O 对象关联的文件句柄。pfnio:指向 I/O 完成回调函数的指针。该回调函数在 I/O 操作完成时被调用。pv:可选参数,指向传递给回调函数的上下文数据的指针。pcbe:可选参数,指向线程池回调环境的指针,可用于自定义线程池行为。可以传递NULL。
返回值:
如果函数调用成功,将返回指向新创建的线程池 I/O 对象的指针(PTP_IO)。如果函数调用失败,将返回 NULL,您可以通过调用 GetLastError 获取错误信息。
2.StartThreadpoolIo函数
StartThreadpoolIo 函数是 Windows API 中用于启动异步 I/O 操作的函数。它告诉线程池监视指定的 I/O 对象,并在 I/O 操作完成时调用回调函数。这个函数通常与 WaitForSingleObject 或其他等待函数一起使用,以等待 I/O 操作的完成。
函数原型:
VOID StartThreadpoolIo( PTP_IO pio );
参数解释:
pio:指向线程池 I/O 对象的指针,通过CreateThreadpoolIo函数创建。
3.CloseThreadpoolIo函数
CloseThreadpoolIo 函数是 Windows API 中用于关闭线程池 I/O 对象的函数。线程池 I/O 对象用于异步 I/O 操作的管理。当不再需要线程池 I/O 对象时,应使用 CloseThreadpoolIo 函数来释放相关资源。
函数原型:
VOID CloseThreadpoolIo( PTP_IO pio );
参数解释:
pio:指向要关闭的线程池 I/O 对象的指针,通过CreateThreadpoolIo函数创建。
示例代码:
#include <Windows.h>
#include <stdio.h>
VOID CALLBACK IoCallback(
PTP_CALLBACK_INSTANCE instance,
PVOID context,
PVOID overlapped,
ULONG ioResult,
ULONG_PTR numberOfBytesTransferred,
PTP_IO io) {
printf("文件写入完成\n");
}
int main() {
HANDLE hFile = CreateFile(TEXT("test.txt"), GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0);
if (hFile == INVALID_HANDLE_VALUE) {
printf("create file failed, errcode:%d\n", GetLastError());
}
PTP_IO ptpIo = CreateThreadpoolIo(hFile, IoCallback, NULL, NULL);
StartThreadpoolIo(ptpIo);
char buffer[] = "hello world";
DWORD writeCount = 0;
OVERLAPPED ol = { 0 };
WriteFile(hFile, (LPCVOID)buffer, strlen(buffer), &writeCount, &ol);
CloseHandle(hFile);
getchar();
CloseThreadpoolIo(ptpIo);
return 1;
}

浙公网安备 33010602011771号