具体情况参考《windows核心编程》第五版的第十章第十一章
(Vista以上)
MSDN示例http://msdn.microsoft.com/en-us/library/windows/desktop/ms686980(v=vs.85).aspx
IO完成端口
1.创建空的IO完成端口,保存其句柄。
CompletePort = CreateIoCompletionPort(
INVALID_HANDLE_VALUE,
NULL,
NULL,
0);
2.创建工作线程,将IO完成端口传入
// Create threads.
for(int i=0; i<SystenInfo.dwNumberOfProcessors*2; i++)
{
HANDLE hThread = CreateThread(NULL,
0,
IOCPWorkThread,
CompletePort,
0,
NULL);
CloseHandle(hThread);
}
3.在本进程的任意线程中,关联IOCP与IO设备,进行IO操作。。
if ((CreateIoCompletionPort((HANDLE)IO设备句柄,CompetionPort,(DWORD)KEY,0)) == NULL)
{
printf("CreateIoCompletionPort failed with error%d"n",GetLastError());
return 0;
}
IO操作
while (TRUE)
{
...
if (GetQueuedCompletionStatus(ComplectionPort,&BytesTransferred,(LPDWORD)&KEY, (LPOVERLAPPED*)&PerIOData,INFINITE) == 0)
{
printf("GetQueuedCompletionStatus failed with error%d"n",GetLastError());
return 0;
}
switch (KEY)
{
//某个IO操作已完成。
...
}
...
}
5.(可选)使用PostQueuedCompletionStatus模拟IO操作。工作线程可以通过GetQueuedCompletionStatus获得模拟的IO操作的完成通知。例如可以在用户取消操作时,模拟几个(工作线程数)IO操作。工作线程获得该操作完成的通知后,退出线程。
----------------------------------------------------------------------
线程池作用
1:以异步方式调用函数
2:每隔一段时间调用一个函数
3:在内核对象触发时调用一个函数(可用于非窗口程序的计时器)
4:在异步I/O请求完成时调用一个函数
只关注4.
1.创建IO线程池并关联IO设备。
PTP_IO WINAPI CreateThreadpoolIo( __in HANDLE fl,//我们打开的io设备句柄 //Overlapped flag __in PTP_WIN32_IO_CALLBACK pfnio, __inout_opt PVOID pv, __in_opt PTP_CALLBACK_ENVIRON pcbe );
2.声明一个回调函数,传给1中的第二个参数。
VOID CALLBACK 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 );3.每次IO操作前,关联线程池内部的IO完成端口。
VOID WINAPI StartThreadpoolIo(
__inout PTP_IO pio//1中返回的线程池句柄
);
4.IO操作返回错误码不是IO_ERROR_PENDING时,或者IO操作的结果不需要再被关注时:
使线程池停止调用回调函数。
VOID WINAPI CancelThreadpoolIo(
__inout PTP_IO pio//1中返回的线程池句柄
);
5.(可选)在其他线程中等待IO操作完成(调用回调函数之前进行)。
VOID WINAPI WaitForThreadpoolIoCallbacks(
__inout PTP_IO pio,
__in BOOL fCancelPendingCallbacks//是否调用回调函数。
);
6.(可选)回调函数的终止操作。
---------------
-------------------------------------------------------------------
对线程池进行定制(可选):
7.自定义线程池。
7.1
(使用InitializeThreadpoolEnvironment函数创建PTP_CALLBACK_ENVIRON pcbe参数,传递给
CreateThreadpoolIo,线程池加入默认清理组)
7.2
// Initialize the private thread pool
g_pThreadPool = CreateThreadpool(NULL);
// Change min=2 / max=4 thread pool parameters
SetThreadpoolThreadMaximum(g_pThreadPool, 4);
SetThreadpoolThreadMinimum(g_pThreadPool, 2);
// Reset the callback environment
// Note: this is an inline function from winbase.h
// that calls TpInitializeCallbackEnviron() in winnt.h.
// -->
// CallbackEnviron->Version = 1;
// CallbackEnviron->Pool = NULL;
// CallbackEnviron->CleanupGroup = NULL;
// CallbackEnviron->CleanupGroupCancelCallback = NULL;
// CallbackEnviron->RaceDll = NULL;
// CallbackEnviron->ActivationContext = NULL;
// CallbackEnviron->FinalizationCallback = NULL;
// CallbackEnviron->u.Flags = 0;
InitializeThreadpoolEnvironment(&g_callbackEnvironment);
// Associate our private thread pool with the callback environment
// Note: this is an inline function from winbase.h
// that calls TpSetCallbackThreadpool() in winnt.h.
// -->
// CallbackEnviron->Pool = Pool;
SetThreadpoolCallbackPool(&g_callbackEnvironment, g_pThreadPool);
...使用线程池
...
8.自定义的线程池(7.1)需要得体的销毁(7.2中,调用CloseThreadPoolXXXX时,对应的线程池从默认清理组移除)。
8.1 首先使用CreateThreadpoolCleanupGroup创建一个清理组。
8.2 然后使用SetThreadpoolCallbackCleanupGroup将清理组与一个或者多个线程池绑定。
该函数的第三个参数是一个回调函数,将在清理组被取消的时候调用。
8.3 销毁线程池。
VOID WINAPI CloseThreadpoolCleanupGroupMembers( __inout PTP_CLEANUP_GROUP ptpcg, __in BOOL fCancelPendingCallbacks,//是否取消 已经提交但尚未处理的IO操作。。 __inout_opt PVOID pvCleanupContext );如果第二个参数是true,则会调用8.2中的回调函数。
如果第二个参数是true,则第三个参数无用。
8.4
释放清理组资源
VOID WINAPI CloseThreadpoolCleanupGroup( __inout PTP_CLEANUP_GROUP ptpcg );
销毁清理组环境变量
VOID DestroyThreadpoolEnvironment( __inout PTP_CALLBACK_ENVIRON pcbe );
关闭线程池
VOID WINAPI CloseThreadpool( __inout PTP_POOL ptpp );