《Windows核心编程》读书笔记——Windows线程池
来源:互联网 发布:sql force 编辑:程序博客网 时间:2024/06/05 19:58
在JeffreyRichter的《windows核心编程》里提到的windows线程池功能,他把这些功能分为四类:
以异步的方式来调用一个函数;
每隔一段时间调用一个函数;
当内核对象触发的时候调用一个函数;
当异步I/O请求完成的时候调用一个函数;
以下按这四种类型功能,结合其调用函数接口和程序例子,来详细讨论其用法。
以异步的方式来调用一个函数
直接以异步方式调用函数也有两种API方式。
隐式控制工作项
这种方式需要两个函数配合使用:需要在线程池中获取线程来调用的函数必须以SimpleCallback函数指针的方式声明,再在主线程中使用用TrySubmitThreadpoolCallback函数设置此回调函数。TrySubmitThreadpoolCallback函数会调用PostQueuedCompletionStatus来将这个SimpleCallback函数的工作项加入到线程池队列中,如果成功的话,返回TRUE,失败返回FALSE。SimpleCallback声明的函数是否立即调用要看CPU的调度。
VOIDCALLBACK SimpleCallback(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_Inout_opt_ PVOID Context
);
BOOLWINAPI TrySubmitThreadpoolCallback(
_In_ PTP_SIMPLE_CALLBACK pfns,
_Inout_opt_ PVOID pv,
_In_opt_ PTP_CALLBACK_ENVIRON pcbe
);
我们不需要自己调用CreateThread来产生线程,系统会为我们的进程创建一个默认的线程池,并让线程池中的一个线程来调用我们的回调函数。这个线程池是windows精心设计的,其原理在《windows核心编程》里面讲述了一些,我尽量找多一些资料佐证这个说法。
下面一个简单的例子展示了隐式控制工作项的这两个函数的使用。
#include "stdafx.h"
#include <windows.h>
VOID CALLBACK MySimpleCallBack(PTP_CALLBACK_INSTANCEInstance,PVOIDContext)
{
_tprintf(_T("This iscalling Test_1_SimpleCallBack!"));
return;
}
int main(void)
{
BOOL ret = TrySubmitThreadpoolCallback(MySimpleCallBack,NULL,NULL);
Sleep(10000);
}
以上的例子有一个明显的问题,没有对MySimpleCallBack调用的线程做同步的等待。如果主线程main已经退出,但MySimpleCallBack函数所在线程还在执行,可能造成的后果是未定义的。后面会讨论怎么解决这个问题,这里不详细展开。还应该注意,TrySubmitThreadpoolCallback不是一定可以调用成功的,在某些情况下,函数内部做线程调度的工作会遇到很多问题。
显式的控制工作项
有时我们可能需要先创建多个工作项,然后逐个加入到线程池中执行,这个时候(也是通常的时候)需要使用显式控制工作项的函数。
使用CreateThreadpoolWork函数创建工作项,线程池会调用这个函数给出的回调函数参数WorkCallback函数指针,使用SubmitThreadpoolWork提交工作项,使用WaitForThreadpoolWorkCallbacks等待工作项完成的事件,最后,使用CloseThreadpoolWork关闭工作项。下面的这些函数的原型。
创建工作项,传进工作需要的回调函数:
PTP_WORKWINAPI CreateThreadpoolWork(
_In_ PTP_WORK_CALLBACK pfnwk,
_Inout_opt_ PVOID pv,
_In_opt_ PTP_CALLBACK_ENVIRON pcbe
);
供线程调用的回调函数原型:
VOIDCALLBACK WorkCallback(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_Inout_opt_ PVOID Context,
_Inout_ PTP_WORK Work
);
提交工作项,让线程池创建一个新线程去调用回调函数:
VOIDWINAPI SubmitThreadpoolWork(
_Inout_ PTP_WORK pwk
);
等待工作项的线程完成回调函数调用:
VOIDWINAPI WaitForThreadpoolWorkCallbacks(
_Inout_ PTP_WORK pwk,
_In_ BOOL fCancelPendingCallbacks
);
关闭工作项:
VOIDWINAPI CloseThreadpoolWork(
_Inout_ PTP_WORK pwk
);
下面上例子说明一个极简单的调用情景:
VOID CALLBACK MyWorkCallback(PTP_CALLBACK_INSTANCEInstance,PVOIDParameter,PTP_WORKWork)
{
_tprintf(_T("This iscalling Test_1_WorkCallback!"));
return;
}
int main(void)
{
PTP_WORKpwWork =CreateThreadpoolWork(MyWorkCallback,NULL,NULL);
SubmitThreadpoolWork(pwWork);
WaitForThreadpoolWorkCallbacks(pwWork,FALSE);
CloseThreadpoolWork(pwWork);
return 0;
}
每隔一段时间调用一个函数
CreateThreadpoolTimer
PTP_TIMERWINAPI CreateThreadpoolTimer(
_In_ PTP_TIMER_CALLBACK pfnti,
_Inout_opt_ PVOID pv,
_In_opt_ PTP_CALLBACK_ENVIRON pcbe
);
VOIDCALLBACK TimerCallback(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_Inout_opt_ PVOID Context,
_Inout_ PTP_TIMER Timer
);
SetThreadpoolTimer
VOIDWINAPI SetThreadpoolTimer(
_Inout_ PTP_TIMER pti,
_In_opt_ PFILETIME pftDueTime,
_In_ DWORD msPeriod,
_In_opt_ DWORD msWindowLength
);
IsThreadpoolTimerSet
BOOLWINAPI IsThreadpoolTimerSet(
_Inout_ PTP_TIMER pti
);
WaitForThreadpoolTimerCallbacks
VOIDWINAPI WaitForThreadpoolTimerCallbacks(
_Inout_ PTP_TIMER pti,
_In_ BOOL fCancelPendingCallbacks
);
CloseThreadpoolTimer
VOIDWINAPI CloseThreadpoolTimer(
_Inout_ PTP_TIMER pti
);
同样以一个简单的例子说明使用情景:
VOID CALLBACK
MyTimerCallback(PTP_CALLBACK_INSTANCEInstance, PVOIDParameter,PTP_TIMERTimer)
{
_tprintf(_T("MyTimerCallback:timer has fired.\n"));
}
int main(void)
{
BOOL ret;
FILETIMEFileDueTime;
ULARGE_INTEGERulDueTime;
// Create a timerwith the same callback environment.
PTP_TIMERtimer =NULL;
PTP_TIMER_CALLBACKtimercallback =MyTimerCallback;
timer = CreateThreadpoolTimer(timercallback,NULL,NULL);
if (NULL ==timer)
{
_tprintf(_T("CreateThreadpoolTimerfailed. LastError: %u\n"),
GetLastError());
}
// Set the timerto fire in one second.
ulDueTime.QuadPart = (ULONGLONG)-(1 * 10 * 1000 * 1000);
FileDueTime.dwHighDateTime =ulDueTime.HighPart;
FileDueTime.dwLowDateTime =ulDueTime.LowPart;
ret = IsThreadpoolTimerSet(timer);
SetThreadpoolTimer(timer,&FileDueTime,0,0);
ret = IsThreadpoolTimerSet(timer);
Sleep(5000);
WaitForThreadpoolTimerCallbacks(timer,FALSE);
CloseThreadpoolTimer(timer);
return 0;
}
当内核对象触发的时候调用一个函数
这种情况是通过在线程池中创建一个等待Event发生的线程,异步完成工作的情景。
CreateThreadpoolWait
SetThreadpoolWait
WaitForThreadpoolWaitCallbacks
CloseThreadpoolWait
同样以例子说明情景:
VOID CALLBACK
MyWaitCallback(
PTP_CALLBACK_INSTANCEInstance,
PVOID Parameter,
PTP_WAIT Wait,
TP_WAIT_RESULT WaitResult
)
{
// Do somethingwhen the wait is over.
_tprintf(_T("MyWaitCallback:wait is over.\n"));
}
int main(void)
{
PTP_WAITWait =NULL;
PTP_WAIT_CALLBACKwaitcallback =MyWaitCallback;
HANDLE hEvent = NULL;
UINT i = 0;
UINT rollback = 0;
// Create anauto-reset event.
hEvent =CreateEvent(NULL,FALSE,FALSE,NULL);
if (NULL ==hEvent)
{
// Error Handling
return;
}
Wait = CreateThreadpoolWait(waitcallback,NULL,NULL);
if(NULL ==Wait)
{
_tprintf(_T("CreateThreadpoolWaitfailed. LastError: %u\n"),
GetLastError());
return -1;
}
// Need tore-register the event with the wait object
// each timebefore signaling the event to trigger the wait callback.
for (i = 0;i <5; i ++)
{
SetThreadpoolWait(Wait, hEvent, NULL);
SetEvent(hEvent);
// Delay forthe waiter thread to act if necessary.
Sleep(500);
// Block hereuntil the callback function is done executing.
WaitForThreadpoolWaitCallbacks(Wait,FALSE);
}
}
当异步I/O请求完成的时候调用一个函数
CreateThreadpoolIo
StartThreadpoolIo
WaitForThreadpoolIoCallbacks
CancelThreadpoolIo
CloseThreadpoolIo
VOIDCALLBACK IoCompletionCallback(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_Inout_opt_ PVOID Context,
_Inout_opt_ PVOID Overlapped,
_In_ ULONG IoResult,
_In_ ULONG_PTR NumberOfBytesTransferred,
_Inout_ PTP_IO Io
);
目前我无法正确使用这个系列函数,有待后续学习后修改。以下是不能调用回调函数的代码,问题还没查清楚。
VOID CALLBACK WriteIoCompletionCallback(
_Inout_ PTP_CALLBACK_INSTANCEInstance,
_Inout_opt_ PVOID Context,
_Inout_opt_ PVOID Overlapped,
_In_ ULONGIoResult,
_In_ ULONG_PTRNumberOfBytesTransferred,
_Inout_ PTP_IOIo
)
{
_tprintf(_T("WriteIoCompletionCallbackcalling"));
return ;
}
int main(void)
{
TCHAR readfilename[] = _T("d:\\test\\test.txt");
TCHAR writefilename[] = _T("d:\\test\\writetest.txt");
PTP_WIN32_IO_CALLBACKreadcallback =ReadIoCompletionCallback;
PTP_WIN32_IO_CALLBACKwritecallback =WriteIoCompletionCallback;
// 以OVERLAPPED方式打开源文件,以备读出
HANDLE hFileRead = CreateFile(readfilename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING|FILE_FLAG_OVERLAPPED,
NULL);
// 以OVERLAPPED方式打目标文件,以备写入
HANDLE hFileWrite = CreateFile(writefilename,
GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING,NULL);
PTP_IO readThreadPool = CreateThreadpoolIo(hFileRead,readcallback,NULL,NULL);
StartThreadpoolIo(readThreadPool);
//PTP_IOwriteThreadPool = CreateThreadpoolIo(hFileWrite,writecallback,NULL,NULL);
//StartThreadpoolIo(writeThreadPool);
PVOID pvData = VirtualAlloc(NULL,1024,MEM_COMMIT,PAGE_READWRITE);
OVERLAPPEDoverlapped;
overlapped.Internal =overlapped.InternalHigh = 0;
overlapped.Offset =overlapped.OffsetHigh = 0;
::ReadFile(hFileRead,pvData,1024,NULL,&overlapped);
Sleep(30000);
WaitForThreadpoolIoCallbacks(readThreadPool,FALSE);
//WaitForThreadpoolIoCallbacks(writeThreadPool,FALSE);
return 0;
}
- 《Windows核心编程》读书笔记——Windows线程池
- 《Windows核心编程》读书笔记十一 Windows线程池
- Windows核心编程<读书笔记六> 线程
- 《Windows核心编程》读书笔记六 线程基础
- 《Windows核心编程》读书笔记十六 线程栈
- 《Windows核心编程》读书笔记——作业
- Windows核心编程<读书笔记十一>线程池的使用
- Windows核心编程读书笔记1——线程(1)线程基础
- Windows核心编程读书笔记2——线程(2)线程内幕
- Windows核心编程读书笔记4——线程(4)当前线程句柄与伪句柄
- Windows核心编程读书笔记
- Windows 核心编程读书笔记
- Windows核心编程读书笔记
- Windows 核心编程 -- 读书笔记
- windows核心编程读书笔记
- 《Windows核心编程》读书笔记
- 《Windows核心编程》读书笔记
- 【读书笔记】Windows核心编程
- 在App Store里混,如何写好关键词?
- SQL, PL/SQL 之NUMBER数据类型
- DMZ主机(路由器)
- XPath基本概念(一)
- C++ 带有默认参数的虚函数
- 《Windows核心编程》读书笔记——Windows线程池
- HTML基础
- Android模拟器无法上网问题
- 会话管理--session
- Web测试工具Selenium:如何选取元素
- BitmapImage转为byte_array,byte_array转为Image控件画到界面中
- Java高级面试题
- Flex AIR基础之标题栏更改
- Event对象