Windows的"线程池"不仅仅是个线程管理的池子。它有很多高级作用。 1:以异步方式调用函数 2:每隔一段时间调用一个函数 3:在内核对象触发时调用一个函数 4:在异步I/O请求完成时调用一个函数 第一个方式,显然就是普通的"线程池"都能做到的事情。用QueueUserWorkItem函数替代CreateThread来创建一个新的线程(例如socket监听返回一个客户端的连接)。 第二个方式,是计时器的作用。Windows GUI的计时器是和HWND绑定的,一次声明一个计时器,计时器结束的时候需要重新设定,用起来麻烦,而且是和消息队列绑定,无法用于复杂的后台服务。Windows线程池则解决了这个问题。 第三个方式,类似于Overlapped IO和线程同步编程。当然,线程同步的一堆复杂问题,已经由线程池为我们解决了,不再需要头疼了。 第四个方式,类似于AIO(APC),我们不再需要为每个I/O操作去指定Completion的回调操作,而是将这个回调注册给线程池统一管理。 第一个方式不用再举例,第四个方式要放在IOCP里面阐述。本文只讨论二,三两种方式。 第二个方式显然可以用于某种时间触发----下面这个例子声明了两个定时器,一个1s,一个2.5s。和直接用Sleep有什么不同呢? Sleep不管之前之后消耗了多少时间,都Sleep一个固定的区间,而Timer则是在精确的时间点唤醒回调函数,不受系统负载和程序cpu占用情况的影响。
#include "stdafx.h"
#include<windows.h>
#include<stdio.h>
int count=0;
HANDLE hEvent,tq,timer1,timer2;
void __stdcall f1(PVOID,BOOL){
printf("计时器1: 1s %d\n",++count);
if(count>20)SetEvent(hEvent);
}
void __stdcall f2(PVOID,BOOL){
printf("计时器2: 2.5s %d\n",++count);
if(count>20)SetEvent(hEvent);
}
int _tmain(int argc, _TCHAR* argv[])
{
if(NULL==(hEvent=CreateEvent(NULL,FALSE,FALSE,"myevent"))){
printf("CreateEvent失败:%d\n",GetLastError());
return 1;
}
ResetEvent(hEvent);
if(NULL==(tq=CreateTimerQueue())){
printf("CreateTimerQueue失败:%d\n",GetLastError());
return 1;
}
if(!(CreateTimerQueueTimer(&timer1,tq,(WAITORTIMERCALLBACK)f1,0,1000,1000,0)
&&CreateTimerQueueTimer(&timer2,tq,(WAITORTIMERCALLBACK)f2,0,2500,2500,0))){
printf("CreateTimerQueueTimer失败:%d\n",GetLastError());
return 1;
}
printf("开始计时\n");
WaitForSingleObject(hEvent,INFINITE);
DeleteTimerQueueTimer(tq,timer1,INVALID_HANDLE_VALUE);
DeleteTimerQueueTimer(tq,timer2,INVALID_HANDLE_VALUE);
DeleteTimerQueueEx(tq,INVALID_HANDLE_VALUE);
return 0;
}
|
程序运行输出: 开始计时 计时器1: 1s 1 计时器1: 1s 2 计时器2: 2.5s 3 计时器1: 1s 4 计时器1: 1s 5 计时器2: 2.5s 6 计时器1: 1s 7 计时器1: 1s 8 计时器1: 1s 9 计时器2: 2.5s 10 计时器1: 1s 11 计时器1: 1s 12 计时器1: 1s 13 计时器2: 2.5s 14 计时器1: 1s 15 计时器1: 1s 16 计时器2: 2.5s 17 计时器1: 1s 18 计时器1: 1s 19 计时器1: 1s 20 计时器2: 2.5s 21 Press any key to continue . . . 第三种情况,可以在上面的程序基础上改,把SetEvent的事件对象计数器,放到线程池里面去,让RegisterWaitForSingleObject来处理: #include "stdafx.h"
#include<windows.h>
#include<stdio.h>
int count=0;
HANDLE hEvent,tq,timer1,hWait;
void __stdcall f(PVOID,BOOL){
printf("计时器1: 1s %d\n",++count);
}
void __stdcall reg(PVOID pParam,BOOL){
HANDLE hEvent=*(HANDLE*)(pParam);
SetEvent(hEvent);
}
int _tmain(int argc, _TCHAR* argv[])
{
if(NULL==(hEvent=CreateEvent(NULL,FALSE,FALSE,"myevent"))){
printf("CreateEvent失败:%d\n",GetLastError());
return 1;
}
ResetEvent(hEvent);
if(NULL==(tq=CreateTimerQueue())){
printf("CreateTimerQueue失败:%d\n",GetLastError());
return 1;
}
if(!CreateTimerQueueTimer(&timer1,tq,(WAITORTIMERCALLBACK)f,0,1000,1000,0)){
printf("CreateTimerQueueTimer失败:%d\n",GetLastError());
return 1;
}
printf("开始计时\n");
RegisterWaitForSingleObject(&hWait,hEvent,(WAITORTIMERCALLBACK)reg,&hEvent,4000,0);
WaitForSingleObject(hEvent,INFINITE);
DeleteTimerQueueTimer(tq,timer1,INVALID_HANDLE_VALUE);
DeleteTimerQueueEx(tq,INVALID_HANDLE_VALUE);
return 0;
}
|
程序输出是: 开始计时 计时器1: 1s 1 计时器1: 1s 2 计时器1: 1s 3 计时器1: 1s 4 Press any key to continue . . .
|