Windows 核心编程 11 windows 线程池
来源:互联网 发布:中世纪2优化大百科 编辑:程序博客网 时间:2024/05/21 23:31
Windows 线程池
本节内容有:
1 以异步方式调用函数
windows 线程池新的线程池函数有异步方式的函数原型
VOID NTAPI SimpleCallBack(PTP_CALLBACK_INSTANCE pInstance,PVOID pvContext);
提交一个请求 调用成功返回TRUE,失败返回FALSE
BOOL TrySubmitThreadpoolCallback(PTP_SIMPLE_CALLBACK pfnCallBack,PVOID pvContext,PTP_CALLBACK_ENVIRON pcbe);
创建一个工作项
PTP_WORD CreateThreadpoolWork(PTP_WORD_CALLBACK pfnwordHandler,PVOID PVcontxt,PTP_callBack_Environ pcbe);
工作项的回调函数
VOID CallBack wordCallBack(PTP_CALLBACK_INSTANCE Instance,PVOID Context,ptp_word word);
向线程池提交一个请求void SubmitThreadpoolword(PTP_WORD pword);
取消已经提交的工作项或者将自己挂起void WaitforThreadpoolWordCallbacks(PTP_WORD Pword,BOOL bCancelPendingCallbacks);
不需要一个工作项时调用
void CloseThreadpoolWord(PTP_WORD pwk);
异步函数的代码在最下面
2 每隔一段时间调用一个函数
有时应用程序需要在某些时间执行某些任务,windos 提供了可等待的计时器内核对象,它使我们很容易就能够得到一个基于时间的通知。
我们可以使用线程池函数来管理可等待计时器,包括重置和等待下一次触发。
为了将一个工作项安排在某个时间执行,我们必须定义一个回调函数,函数声明如下:
VOID CALLBACK TimeoutCallBack(PTP_CALLBACK_INSTANCE pInstance, 回调函数终止操作讲解
PVOID pvContext, 下面函数传过来的
PTP_TIMER pTimer); 下面函数的返回值
然后调用下面的函数通知线程池应该在何时调用我们的函数:
PTP_TIMER CreateThreadpoolTimer(
PTP_TIMER_CALLBACK pfnTimerCallBack,
PVOID pvcontext,
PTP_CALLBACK_ENVIRON pcbe);
第一个参数是函数指针,第2个参数是传递给回调函数的值,参数3 后面讲
当我们想要向线程池注册计时器的时候,应该调用SetThreadpoolTimer函数:
VOIDWINAPISetThreadpoolTimer(
__inout PTP_TIMER pti,
__in_opt PFILETIME pftDueTime,
__in DWORD msPeriod,
__in_opt DWORD msWindowLength );
参数 pti 用来标识CreateThreadpoolTimer返回的TP_TIMER 对象.
参数ptfDueTime 表示第一次调用回调函数应该是什么时候,我们可以传一个负值(微妙为单位)来指定相对时间. 该时间相对于SetThreadpoolTimer的时间,-1是一个特例,表示
立即开始。 为了指定一个绝对时间,应该为正值,100纳秒为单位,从1600年1月1日算起.
参数 msPeriod 表示如果只想触发一次,传0即可,如果不传0,单位是微秒。表示第一次调用以后,以后按这个时间循环调用.
参数 mswindoLength 表示增加一个随机性,如果有多个定时器也冲突。
在设置了计时器之后,我们还可以通过调用SetThreadpoolTimer 并在pti参数中传入以前设置的计时器指针,来对已有的计时器修改
我们传入pftDueTime 为NULL时,这等于告诉线程池停止调用我们的TimerCallBack函数.这不失为一种将计时器暂停但又不必销毁计时器对象的好办法,尤其在回调函数内部,更是如此。
IsThreadpoolTimerSet 来确定某个计时器是否被设置(pftDuetime不为NULL);
WINBASEAPI BOOL WINAPI IsThreadpoolTimerSet( __inout PTP_TIMER pti )
来让线程等待一个定时器完成调用下面函数
WaitForThreadpoolTimerCallbacks();
CloseThreadpoolTimer();函数来释放计时器的内存资源,他们的前面介绍的都一样,如异步函数调用.
下面介绍线程池计时器的使用:见最下 Timed Message Box
3 在内核对象触发时调用一个函数
首先编写一个符合下面的函数原型:
VOID CALLBACK WaitCallback(PTP_CALLBACK_INSTANCE pInstance,PTP_WAIT Wait,TP_WAIT_RESULT WaitResult);】
然后通过调用CreateThreadpoolWait
来创建一个线程池等待对象
PTP_WAIT WINAPI CreateThreadpoolWait( __in PTP_WAIT_CALLBACK pfnwa,
__inout_opt PVOID pv,
__in_opt PTP_CALLBACK_ENVIRON pcbe );
当我们创建完成后,我们调用下面的函数来将一个内核对象绑定到这个线程池:
VOID WINAPI SetThreadpoolWait(
__inout PTP_WAIT pwa, 创建一个等待对象
__in_opt HANDLE h, 需要等待的内核对象
__in_opt PFILETIME pftTimeout 表示最长花多少时间等待 0表示不等待,负值表示相对时间正值表示绝对时间,NULL表示一直等下去 );
当内核对象触发或者等待超时,那么线程池中的某个线程会调用我们的回调函数,返回值有3个类型。
WAIT_OBJECT_0WAIT_TIMEOUTWAIT_ABANDONED_0
waitForThreadpoolWaitCallbacks函数来等待一个等待项完成
CloseThreadpoolWait函数来释放一个等待项
线程池的内核对象触发代码在最下面:
4 在异步IO请求完成时调用一个函数
CreateThreadpoolIo来创建一个IO线程池
5 回调函数的终止操作
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Windows 核心编程全部源代码在这个链接上:http://download.csdn.net/detail/woleiwei/5716243
//异步函数的代码
第11章 代码 11-Batch
/******************************************************************************Module: Batch.cppNotices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre******************************************************************************/#include "..\CommonFiles\CmnHdr.h" /* See Appendix A. */#include <Windowsx.h>#include <WinBase.h>#include <WinNT.h>// C RunTime Header Files#include <stdlib.h>#include <malloc.h>#include <memory.h>#include <tchar.h>#include <strsafe.h>#include "Batch.h"//////////////////////////////////////////////////////////////////////////////// Global variablesHWND g_hDlg = NULL;//窗口句柄PTP_WORK g_pWorkItem = NULL;//工作项volatile LONG g_nCurrentTask = 0;//当前工作项数量// Global definitions#define WM_APP_COMPLETED (WM_APP+123)//////////////////////////////////////////////////////////////////////////////void AddMessage(LPCTSTR szMsg) { HWND hListBox = GetDlgItem(g_hDlg, IDC_LB_STATUS); ListBox_SetCurSel(hListBox, ListBox_AddString(hListBox, szMsg));}//////////////////////////////////////////////////////////////////////////////void NTAPI TaskHandler(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work) {//返回值是增加后的值 LONG currentTask = InterlockedIncrement(&g_nCurrentTask); TCHAR szMsg[MAX_PATH]; StringCchPrintf( szMsg, _countof(szMsg), TEXT("[%u] Task #%u is starting."), GetCurrentThreadId(), currentTask); AddMessage(szMsg); // Simulate a lot of work Sleep(currentTask * 1000); StringCchPrintf( szMsg, _countof(szMsg), TEXT("[%u] Task #%u is done."), GetCurrentThreadId(), currentTask); AddMessage(szMsg); //返回值是减少后的值 最后一个处理完毕了 if (InterlockedDecrement(&g_nCurrentTask) == 0) { // Notify the UI thread for completion. PostMessage(g_hDlg, WM_APP_COMPLETED, 0, (LPARAM)currentTask); }}//////////////////////////////////////////////////////////////////////////////void OnStartBatch() { // Disable Start button Button_Enable(GetDlgItem(g_hDlg, IDC_BTN_START_BATCH), FALSE); AddMessage(TEXT("----Start a new batch----")); // Submit 4 tasks by using the same work item //提交一个工作项用于4个任务 SubmitThreadpoolWork(g_pWorkItem); SubmitThreadpoolWork(g_pWorkItem); SubmitThreadpoolWork(g_pWorkItem); SubmitThreadpoolWork(g_pWorkItem); AddMessage(TEXT("4 tasks are submitted."));}//////////////////////////////////////////////////////////////////////////////void Dlg_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify) { switch (id) { case IDOK: case IDCANCEL: EndDialog(hWnd, id); break; case IDC_BTN_START_BATCH: OnStartBatch(); break; }}BOOL Dlg_OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam) { // Keep track of main dialog window for error messages g_hDlg = hWnd; return(TRUE);}//////////////////////////////////////////////////////////////////////////////INT_PTR WINAPI Dlg_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { chHANDLE_DLGMSG(hWnd, WM_INITDIALOG, Dlg_OnInitDialog); chHANDLE_DLGMSG(hWnd, WM_COMMAND, Dlg_OnCommand); case WM_APP_COMPLETED: { TCHAR szMsg[MAX_PATH+1]; StringCchPrintf( szMsg, _countof(szMsg), TEXT("____Task #%u was the last task of the batch____"), lParam); AddMessage(szMsg); // Don't forget to enable the button Button_Enable(GetDlgItem(hWnd, IDC_BTN_START_BATCH), TRUE); } break; } return(FALSE);}int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR pCmdLine, int) { // Create the work item that will be used by all tasks//创建一个工作项用于所有的任务 g_pWorkItem = CreateThreadpoolWork(TaskHandler, NULL, NULL);//参数1 表示回调函数 if (g_pWorkItem == NULL) { MessageBox(NULL, TEXT("Impossible to create the work item for tasks."), TEXT(""), MB_ICONSTOP); return(-1); } DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, Dlg_Proc, _ttoi(pCmdLine)); // Don't forget to delete the work item CloseThreadpoolWork(g_pWorkItem); return(0);}//////////////////////////////// End of File /////////////////////////////////
下面代码是 定时器线程池对象
/******************************************************************************Module: TimedMsgBox.cppNotices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre******************************************************************************/#include "..\CommonFiles\CmnHdr.h" /* See Appendix A. */#include <tchar.h>#include <StrSafe.h>//////////////////////////////////////////////////////////////////////////////// The caption of our message boxTCHAR g_szCaption[100];// How many seconds we'll display the message boxint g_nSecLeft = 0;// This is STATIC window control ID for a message box// 这个ID是 spy++查看到的#define ID_MSGBOX_STATIC_TEXT 0x0000ffff////////////////////////////////////////////////////////////////////////////////定时器回调函数VOID CALLBACK MsgBoxTimeoutCallback( PTP_CALLBACK_INSTANCE pInstance, PVOID pvContext, PTP_TIMER pTimer ){ // NOTE: Due to a thread race condition, it is possible (but very unlikely) // that the message box will not be created when we get here.//通过标题获得窗口句柄 HWND hwnd = FindWindow(NULL, g_szCaption); if (hwnd != NULL) { if (g_nSecLeft == 1) { // The time is up; force the message box to exit. EndDialog(hwnd, IDOK); return; } // The window does exist; update the time remaining. TCHAR szMsg[100]; StringCchPrintf(szMsg, _countof(szMsg), TEXT("You have %d seconds to respond"), --g_nSecLeft); SetDlgItemText(hwnd, ID_MSGBOX_STATIC_TEXT, szMsg); } else { // The window does not exist yet; do nothing this time. // We'll try again in another second. }}int WINAPI _tWinMain(HINSTANCE, HINSTANCE, PTSTR, int) { _tcscpy_s(g_szCaption, _countof(g_szCaption), TEXT("Timed Message Box")); // How many seconds we'll give the user to respond g_nSecLeft = 10; // Create the threadpool timer object PTP_TIMER lpTimer = CreateThreadpoolTimer(MsgBoxTimeoutCallback, NULL, NULL); //第一个参数是 回调函数在前面定义了,后面2个参数没有使用到 if (lpTimer == NULL) { TCHAR szMsg[MAX_PATH]; StringCchPrintf(szMsg, _countof(szMsg), TEXT("Impossible to create the timer: %u"), GetLastError()); MessageBox(NULL, szMsg, TEXT("Error"), MB_OK | MB_ICONERROR); return(-1); } // Start the timer in one second to trigger every 1 second ULARGE_INTEGER ulRelativeStartTime; ulRelativeStartTime.QuadPart = (LONGLONG) -(10000000); // start in 1 second 100纳秒为单位 那么 1000 000 0表示1秒 FILETIME ftRelativeStartTime; ftRelativeStartTime.dwHighDateTime = ulRelativeStartTime.HighPart; ftRelativeStartTime.dwLowDateTime = ulRelativeStartTime.LowPart; SetThreadpoolTimer( lpTimer, &ftRelativeStartTime, // 一个单位表示100纳秒 表示调用这个函数以后,回调函数多久第一次执行 1000, // Triggers every 1000 milliseconds 每1秒触发一次 0 ); MessageBox(NULL, TEXT("You have 10 seconds to respond"), g_szCaption, MB_OK); // Clean up the timerCloseThreadpoolTimer(lpTimer);//如果不关闭线程池对象,那么回调函数会继续运行,直到进程退出 // Let us know if the user responded or if we timed out MessageBox( NULL, (g_nSecLeft == 1) ? TEXT("Timeout") : TEXT("User responded"), TEXT("Result"), MB_OK); return(0);}//////////////////////////////// End of File /////////////////////////////////
3 内核对象线程池函数
#include <iostream>#include <windows.h>#include <Winbase.h>#include <tchar.h>VOID CALLBACK MyWaitCallback( PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WAIT Wait, TP_WAIT_RESULT WaitResult ){// Instance, Parameter, Wait, and WaitResult not used in this example.UNREFERENCED_PARAMETER(Instance);UNREFERENCED_PARAMETER(Parameter);UNREFERENCED_PARAMETER(Wait);UNREFERENCED_PARAMETER(WaitResult);//// Do something when the wait is over.//_tprintf(_T("MyWaitCallback: wait is over.\n"));}VOID DemoNewRegisterWait(){PTP_WAIT Wait = NULL;PTP_WAIT_CALLBACK waitcallback = MyWaitCallback;HANDLE hEvent = NULL;UINT i = 0;UINT rollback = 0;//// Create an auto-reset event.//hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);if (NULL == hEvent) {// Error Handlingreturn;}rollback = 1; // CreateEvent succeededWait = CreateThreadpoolWait(waitcallback,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);// 参数3 表示花多少时间等待 参数2的内核对象触发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 NULL.SetThreadpoolWait(Wait, NULL, NULL);//取消等待项和事件关联关系// Close the wait.CloseThreadpoolWait(Wait);case 1:// Close the event.CloseHandle(hEvent);default:break;}return;}int main( void){DemoNewRegisterWait();return 0;}
#include <windows.h>#include <tchar.h>#include <stdio.h>//// Thread pool wait callback function template//VOIDCALLBACKMyWaitCallback( PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WAIT Wait, TP_WAIT_RESULT WaitResult ){// Instance, Parameter, Wait, and WaitResult not used in this example.UNREFERENCED_PARAMETER(Instance);UNREFERENCED_PARAMETER(Parameter);UNREFERENCED_PARAMETER(Wait);UNREFERENCED_PARAMETER(WaitResult);//// Do something when the wait is over.//_tprintf(_T("MyWaitCallback: wait is over.\n"));}//// Thread pool timer callback function template//VOIDCALLBACKMyTimerCallback(PTP_CALLBACK_INSTANCE Instance,PVOID Parameter,PTP_TIMER Timer){// Instance, Parameter, and Timer not used in this example.UNREFERENCED_PARAMETER(Instance);UNREFERENCED_PARAMETER(Parameter);UNREFERENCED_PARAMETER(Timer);//// Do something when the timer fires.//_tprintf(_T("MyTimerCallback: timer has fired.\n"));}//// This is the thread pool work callback function.//VOIDCALLBACKMyWorkCallback( PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WORK Work ){// Instance, Parameter, and Work not used in this example.UNREFERENCED_PARAMETER(Instance);UNREFERENCED_PARAMETER(Parameter);UNREFERENCED_PARAMETER(Work);BOOL bRet = FALSE;//// Do something when the work callback is invoked.//{_tprintf(_T("MyWorkCallback: Task performed.\n"));}return;}VOIDDemoCleanupPersistentWorkTimer(){BOOL bRet = FALSE;PTP_WORK work = NULL;// a word ItemPTP_TIMER timer = NULL;PTP_POOL pool = NULL;PTP_WORK_CALLBACK workcallback = MyWorkCallback;PTP_TIMER_CALLBACK timercallback = MyTimerCallback;//回调函数环境变量TP_CALLBACK_ENVIRON CallBackEnviron;PTP_CLEANUP_GROUP cleanupgroup = NULL;FILETIME FileDueTime;ULARGE_INTEGER ulDueTime;UINT rollback = 0;//初始化线程池环境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.//SetThreadpoolThreadMaximum(pool, 1);bRet = SetThreadpoolThreadMinimum(pool, 1);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.// Objects created with the same callback environment// as the cleanup group become members of the cleanup group.//SetThreadpoolCallbackCleanupGroup(&CallBackEnviron,cleanupgroup,NULL);//// Create work with the callback environment.//work = CreateThreadpoolWork(workcallback,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);//// Create a timer with the same callback environment.//timer = CreateThreadpoolTimer(timercallback,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.//ulDueTime.QuadPart = (ULONGLONG) -(1 * 10 * 1000 * 1000);FileDueTime.dwHighDateTime = ulDueTime.HighPart;FileDueTime.dwLowDateTime = ulDueTime.LowPart;SetThreadpoolTimer(timer,&FileDueTime,0,0);//// Delay(延迟) for the timer to be fired//Sleep(1500);//// Wait for all callbacks to finish.// CloseThreadpoolCleanupGroupMembers also releases objects// that are members of the cleanup group, so it is not necessary (不必要的)// to call close functions on individual objects // after calling CloseThreadpoolCleanupGroupMembers.//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 members.CloseThreadpoolCleanupGroupMembers(cleanupgroup,FALSE, NULL);case 2:// Clean up the cleanup group.CloseThreadpoolCleanupGroup(cleanupgroup);case 1:// Clean up the pool.CloseThreadpool(pool);default:break;}return;}VOIDDemoNewRegisterWait(){PTP_WAIT Wait = NULL;PTP_WAIT_CALLBACK waitcallback = MyWaitCallback;HANDLE hEvent = NULL;UINT i = 0;UINT rollback = 0;//// Create an auto-reset event.//hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);if (NULL == hEvent) {// Error Handlingreturn;}rollback = 1; // CreateEvent succeededWait = CreateThreadpoolWait(waitcallback,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 NULL.SetThreadpoolWait(Wait, NULL, NULL);// Close the wait.CloseThreadpoolWait(Wait);case 1:// Close the event.CloseHandle(hEvent);default:break;}return;}int main( void){DemoNewRegisterWait();DemoCleanupPersistentWorkTimer();getchar();return 0;}
- Windows 核心编程 11 windows 线程池
- windows核心编程--线程池
- windows核心编程--线程池
- Windows核心编程-----线程池
- windows核心编程---windows线程池
- windows核心编程--线程
- windows 核心编程 线程
- windows核心编程--线程
- windows核心编程--线程
- Windows核心编程--线程
- Windows核心编程-----线程池二
- Windows核心编程(十二)线程池
- 《Windows核心编程》之“线程池”
- windows核心编程--线程高级
- windows核心编程--线程高级
- Windows核心编程:线程基础
- Windows核心编程:线程调度
- 线程基础----Windows核心编程
- PHP 生成条形码: barcodegen
- redis入门
- java枚举类型Enum 整合
- 【LTE被视作从3G向4G演进的主流技术】
- Dundas Chart for asp.net 在win7 64位系统下发布图表不能显示
- Windows 核心编程 11 windows 线程池
- Android 网络编程——HTTP请求的封装
- ubuntu12.10安装android编译环境
- hud 1754 I Hate It
- 快速排序
- jquery删除提示框
- 移动界面控件Essential Studio for Mobile MVC使用教程
- Linux学习笔记之pureftp(五)常见问题
- The connection to adb is down, and a severe error has occured