windows核心编程-线程池
线程池解决多线程难于管理的问题,Windows主要提供如下方式实现
- 异步调用函数:服务器客户端模式下比较适用
- 定时回调函数:避免使用多个定时器占用主线程CPU处理时间
- 内核对象通知状态回调:多个线程等待相同内核对象下适用
- 异步IO请求完成时调用函数:异步IO操作情形下适用
1)异步调用函数实现
使用于服务器端创建线程处理客户端请求情景
MainThread->Wait for Client request->CreateThread handle request-> waitfor client request
使用:
服务器端收到客户端请求时调用
BOOL WINAPI QueueUserWorkItem(
__in LPTHREAD_START_ROUTINE Function,
__in_opt PVOID Context,
__in ULONG Flags
);
需要注意:执行过程中是无序的
DWORD WINAPI WorkProc( __in LPVOID lpParameter ) { DWORD dwThreadID=GetCurrentThreadId(); int i =(int)lpParameter; printf("Thread:%d,time:%d,val:%d\n",dwThreadID,GetTickCount(),i); return 1; } void WorkItemDemo() { for(int i=0;i<100;i++) { QueueUserWorkItem(WorkProc,(PVOID)i,WT_EXECUTEDEFAULT); } }
2)定时回调函数
适用于需要启动定时器且不影响主线程情形
VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired) { if (lpParam == NULL) { printf("TimerRoutine lpParam is NULL\n"); } else { printf("thread:%d Timer routine called. Parameter is %d.\n", GetCurrentThreadId(),*(int*)lpParam); } } int _tmain(int argc, _TCHAR* argv[]) { HANDLE hTimer[10]; HANDLE hTimerQueue=NULL; int arg = 123; // Create the timer queue. hTimerQueue = CreateTimerQueue(); if (NULL == hTimerQueue) { printf("CreateTimerQueue failed (%d)\n", GetLastError()); return 2; } int iArray[10] = {0,1,2,3,4,5,6,7,8,9}; for(int i=0;i<10;i++) { // Set a timer to call the timer routine in 10 seconds. if (!CreateTimerQueueTimer( hTimer+i, hTimerQueue, (WAITORTIMERCALLBACK)TimerRoutine, iArray+i , 100+i*100, 100, 0)) { printf("CreateTimerQueueTimer failed (%d)\n", GetLastError()); return 3; } } // TODO: Do other useful work here //WaitForMultipleObjects(10,hTimer,true,INFINITE); Sleep(60*1000); printf("Call timer routine in 10 seconds...\n"); // Delete all timers in the timer queue. if (!DeleteTimerQueue(hTimerQueue)) printf("DeleteTimerQueue failed (%d)\n", GetLastError()); return 0; }
3)内核对象通知状态回调
适用于多线程等待某个相同内核对象通知,相同等待事件可有多个回调同时进入,在对象属于通知状态时可反复调用多次….
VOID CALLBACK WaitOrTimerCallback0( __in PVOID lpParameter, __in BOOLEAN TimerOrWaitFired ) { //通知状态自动调用 static volatile LONG iCount=0; int i= (int)lpParameter; InterlockedIncrement(&iCount); printf("Thread:%d,val:%d,count:%d\n",GetCurrentThreadId(),i,iCount); } //... RegisterWaitForSingleObject(&hReg[0],hEvent,WaitOrTimerCallback0,0,100,WT_EXECUTEDEFAULT); //… SetEvent(hEvent); //… UnregisterWait(hReg[0]);
4)异步IO请求完成时调用函数
需要注意使用重叠模式创建文件和读写文件,读写需要调用GetOverlappedResult获取读写数据
DWORD g_DwWriten=0; VOID CALLBACK MyFileIOCompletionRoutine( __in DWORD dwErrorCode, __in DWORD dwNumberOfBytesTransfered, __in LPOVERLAPPED lpOverlapped ) { printf("thread:%d,trans:%d\n",GetCurrentThreadId(),dwNumberOfBytesTransfered); } //… hFile = CreateFile(pszFile, // name of the write GENERIC_WRITE, // open for writing 0, // do not share NULL, // default security CREATE_ALWAYS, // overwrite existing FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED , // FILE_FLAG_OVERLAPPED重叠模式 NULL); //… OVERLAPPED ov; ZeroMemory(&ov,sizeof(OVERLAPPED)); if( FALSE == WriteFile(hFile, // open file handle DataBuffer + dwBytesWritten, // start of data to write dwBytesToWrite - dwBytesWritten, // number of bytes to write &dwBytesWritten, // number of bytes that were written &ov) // overlapped 重叠模式 ) { if(GetLastError() != ERROR_IO_PENDING) { printf("Could not write to file (error %d)\n", GetLastError()); CloseHandle(hFile); return 0; } GetOverlappedResult(hFile,&ov,&dwBytesWritten,TRUE); }