Windows系统线程池+利用windows自带的线程池

来源:互联网 发布:大数据分析专业 编辑:程序博客网 时间:2024/06/06 03:43

come from:http://www.fuzhijie.me/?p=65
一直想弄明白Windows的IO完成端口是什么,这个词语每每出现在我眼前时总是伴随着鲜花和赞美,因此我便将其同许多我从来没搞懂过的东西一起归为神秘一类。这两天一直在看《Windows核心编程》,学到了不少东西,但是同别的英文经典一样,中文版经常让我感觉不知所云,我很不喜欢书中的例子都是用C++来写,并且都有图形界面,这阻碍了初学者理解问题的本质,并不是每个人都熟悉Windows的图形界面编程,Windows的API不仅个数多,许多API参数也非常多,如果仅仅是简单类型也就罢了,许多参数又会是复杂的结构体,相比之下,Unix的系统调用就简洁多了。我打算循序渐进,先学习了下Windows自带的线程池的使用,这个东西实现得挺好的,Linux没有提供等同物。

MSDN中对线程池的使用只给出了一个实例,相关的代码网上少得可怜,我只能对这例子视若珍宝,好好研究了一番,去掉一些旁枝末节,添加点注释吧,就当作是读书札记吧。

《Windows核心编程》中将线程池允许我们做的事情归为四类,分别如下:
情景1:以异步方式调用函数
情景2:每隔一段时间调用一个函数
情景3:在内核对象触发时调用一个函数
情景4:在异步I/O请求完成时调用一个函数

MSDN中的这个例子演示了前三种情景,这三种情景下的回调函数的签名各不一样。原程序中没有给清理组设置回调函数,我写了一个清理回调函数,也只是简单地打印出运行代码的线程号等信息而已。

//// Thread pool wait callback function template//////注意这三种回调函数的签名,它们都没有返回值VOIDCALLBACKMyWaitCallback(      PTP_CALLBACK_INSTANCE Instance,      PVOID                 Parameter,      PTP_WAIT              Wait,      TP_WAIT_RESULT        WaitResult      ){printf("%u in MyWaitCallback\n", GetCurrentThreadId());} //// Thread pool timer callback function template//VOIDCALLBACKMyTimerCallback(    PTP_CALLBACK_INSTANCE Instance,    PVOID                 Parameter,    PTP_TIMER             Timer    ){printf("(%u) in MyTimerCallback\n", GetCurrentThreadId());} //// This is the thread pool work callback function.// The callback demonstrates correct behavior when changing the// state of the thread inside the callback function.//// Any changes to the thread state must be restored to original// before exiting the callback routine.//VOIDCALLBACKMyWorkCallback(      PTP_CALLBACK_INSTANCE Instance,      PVOID                 Parameter,      PTP_WORK              Work      ){printf("(%u) in MyWorkCallback\n", GetCurrentThreadId());} VOIDCALLBACKMyCleanupCallback(      PVOID pvObjectContext,      PVOID pvCleanupContext      ){printf("(%u) in MyCleanupCallback\n", GetCurrentThreadId());} VOIDDemoCleanupPersistentWorkTimer(){BOOL bRet = FALSE;PTP_WORK work = NULL;PTP_TIMER timer = NULL;PTP_POOL pool = NULL;TP_CALLBACK_ENVIRON CallBackEnviron;PTP_CLEANUP_GROUP cleanupgroup = NULL;FILETIME FileDueTime;ULARGE_INTEGER ulDueTime;UINT rollback = 0; printf("(%u)in DemoCleanupPersistentWorkTimer\n", GetCurrentThreadId()); //初始化很重要,否则运行到CreateThreadpoolWork将会出错//可以在调试模式下看看TP_CALLBACK_ENVIRON结构体的内容InitializeThreadpoolEnvironment(&CallBackEnviron); //// Create a custom, dedicated thread pool//pool = CreateThreadpool(NULL); if (NULL == pool) {_tprintf(_T("CreateThreadpool failed. LastError: %u\n"),GetLastError());goto main_cleanup;} rollback = 1; // pool creation succeeded //// The thread pool is made persistent simply by setting// both the minimum and maximum threads to 1.////将最大值和最小值都设置为1,若提交几个工作项时,所有的工作项都由这一个线程完成//如果可以开启多个线程,可以看到会有好几个线程一起来完成这些工作项SetThreadpoolThreadMaximum(pool, 1); bRet = SetThreadpoolThreadMinimum(pool, 4); if (FALSE == bRet) {_tprintf(_T("SetThreadpoolThreadMinimum failed. LastError: %u\n"), GetLastError());goto main_cleanup;} //// Create a cleanup group for this thread pool//cleanupgroup = CreateThreadpoolCleanupGroup(); if (NULL == cleanupgroup) {_tprintf(_T("CreateThreadpoolCleanupGroup failed. LastError: %u\n"), GetLastError());goto main_cleanup;} rollback = 2;  // Cleanup group creation succeeded //// Associate the callback environment with our thread pool//SetThreadpoolCallbackPool(&CallBackEnviron, pool); //// Associate the cleanup group with our thread pool//SetThreadpoolCallbackCleanupGroup(&CallBackEnviron,cleanupgroup,&MyCleanupCallback); //// Create work with the callback environment////使用的线程池被包含在CallBackEnviron参数中//如果此处传递NULL进去,将使用一个默认的线程池work = CreateThreadpoolWork((PTP_WORK_CALLBACK) MyWorkCallback,NULL,&CallBackEnviron); if (NULL == work) {_tprintf(_T("CreateThreadpoolWork failed. LastError: %u\n"),GetLastError());goto main_cleanup;} rollback = 3;  // Creation of work succeeded //// Submit the work to the pool. Because this was a pre-allocated// work item (using CreateThreadpoolWork), it is guaranteed// to execute////可以多提交几个工作项试试看,SubmitThreadpoolWork(work);SubmitThreadpoolWork(work);SubmitThreadpoolWork(work);SubmitThreadpoolWork(work); //// Create a timer with the same callback environment//timer = CreateThreadpoolTimer((PTP_TIMER_CALLBACK) MyTimerCallback,NULL, &CallBackEnviron); if (NULL == timer) {_tprintf(_T("CreateThreadpoolTimer failed. LastError: %u\n"),GetLastError());goto main_cleanup;} rollback = 4;  // Timer creation succeeded //// Set the timer to fire in one second////如果为正值,则表示绝对时间,从1600年1月1日开始计算,单位为纳秒//如果为负值,则表示相对时间,单位为微秒//两种情况下单位不一样哦。ulDueTime.QuadPart = (LONGLONG) -(100000000);FileDueTime.dwHighDateTime = ulDueTime.HighPart;FileDueTime.dwLowDateTime  = ulDueTime.LowPart; //定时器只触发一次SetThreadpoolTimer(timer,&FileDueTime,0,0); //// Delay for the timer to be fired////等待线程池中的线程完成定时器中的工作,注意这儿睡眠的值//要大于上面定时器触发的值,否则就看不到结果了。Sleep(15000); //// Wait for all callbacks to finish.// CloseThreadpoolCleanupGroupMembers also calls the cleanup// functions for all the individual objects in the specified// cleanup group.////此时主线程会调用MyCleanupCallback两次,我还没怎么明白清理组的使用方法CloseThreadpoolCleanupGroupMembers(cleanupgroup,FALSE,NULL); //// Already cleaned up the work item with the// CloseThreadpoolCleanupGroupMembers, so set rollback to 2.//rollback = 2;goto main_cleanup; main_cleanup://// Clean up any individual pieces manually// Notice the fall through structure of the switch.// Clean up in reverse order.// switch (rollback) {case 4:case 3:// Clean up the cleanup group membersCloseThreadpoolCleanupGroupMembers(cleanupgroup,FALSE, NULL);case 2:// Clean up the cleanup groupCloseThreadpoolCleanupGroup(cleanupgroup); case 1:// Clean up the poolCloseThreadpool(pool); default:break;} return;} VOIDDemoNewRegisterWait(){PTP_WAIT Wait = NULL;HANDLE hEvent = NULL;UINT i = 0;UINT rollback = 0; printf("(%u)in DemoNewRegisterWait\n", GetCurrentThreadId()); //// Create an auto-reset event//hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (NULL == hEvent) {// Error Handlingreturn;} rollback = 1; // CreateEvent succeeded Wait = CreateThreadpoolWait((PTP_WAIT_CALLBACK) MyWaitCallback,NULL,NULL); if(NULL == Wait) {_tprintf(_T("CreateThreadpoolWait failed. LastError: %u\n"),GetLastError());goto new_wait_cleanup;} rollback = 2; // CreateThreadpoolWait succeeded //// Need to re-register the event with the wait object// each time before signaling the event to trigger the// wait callback//for (i = 0; i < 5; i ++) {SetThreadpoolWait(Wait,hEvent,NULL); //将事业设置成触发态SetEvent(hEvent); //// Delay for the waiter thread to act if necessary//Sleep(500); //// Block here until the callback function is done executing////等待回调函数执行完WaitForThreadpoolWaitCallbacks(Wait, FALSE);} new_wait_cleanup:switch (rollback) {case 2:// Unregister the wait by setting the event to NULLSetThreadpoolWait(Wait, NULL, NULL); // Close waitCloseThreadpoolWait(Wait); case 1:// Close eventCloseHandle(hEvent); default:break;}return;} int main(){DemoCleanupPersistentWorkTimer(); DemoNewRegisterWait(); return 0;}


原创粉丝点击