CreateWaitableTimer与SetWaitableTimer详解

可等待定时器问题:

1. 需要的函数:CreateWaitableTimer,SetWaitableTimer.前者创建一个可等待定时器句柄,后者设置等待定时器触发的条件.我们可以多次调用SetWaitableTimer来重置可等待定时器.重置后之前的定时器将关闭.

2. 主要看两段代码:

代码一:(这段代码在网上出现的概率是较大的)

  1. HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL );  
  2.   
  3. LARGE_INTEGER li;  
  4.   
  5. li.QuadPart = 0;  
  6.   
  7.   
  8. if( !SetWaitableTimer( hTimer,&li,1000,NULL,NULL,FALSE ))  
  9.   
  10. {  
  11.   
  12. CloseHandle( hTimer );  
  13.   
  14. return;  
  15.   
  16. }  
  17.   
  18. while ( 1 )  
  19.   
  20. {  
  21.   
  22. //clock_t c_beg = clock();  
  23.   
  24. WaitForSingleObject( hTimer,INFINITE );  
  25.   
  26. //clock_t end = clock() - c_beg;  
  27.   
  28. //cout<<"time:"<<end<<endl;  
  29.   
  30. cout<<"定时器触发了...\n";  
  31.   
  32. }  
  33.   
  34. CloseHandle(hTimer);  


通过将上面注释的代码放开,我们可以发现:

◆ 前两个定时器出发过程”不稳定”(即它们所耗费的时间并不是1.

◆ 就算是稳定了以后,定时器的差距并不是1s而是1000(毫秒)左右,这就奇怪了.

如果说第二个问题是由于执行clock而产生的误差的话,那么第一个问题则没办法解释.(其实对于clock的时间几乎是可以忽略不计的.)

这样就引入了核心编程里面作者的代码:

代码二:

  1. HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL );  
  2.   
  3. LARGE_INTEGER li;  
  4.   
  5. li.QuadPart = 0;  
  6.   
  7.   
  8. if( !SetWaitableTimer( hTimer,&li,1000,NULL,NULL,FALSE ))  
  9.   
  10. {  
  11.   
  12. CloseHandle( hTimer );  
  13.   
  14. return;  
  15.   
  16. }  
  17.   
  18.   
  19. while ( 1 )  
  20.   
  21. {  
  22.   
  23. clock_t c_beg = clock();  
  24.   
  25. SleepEx( 1000,TRUE );//这里并没有使用WaitForSingleObject,而是使用SleepEx  
  26.   
  27. clock_t end = clock() - c_beg;  
  28.   
  29. cout<<"time:"<<end<<endl;  
  30.   
  31. }  
  32.   
  33. CloseHandle(hTimer);  


运行结果发现正常:每次都是1000(毫秒).

从这里可以间接证明,clock消耗的时间可以忽略不计.

再来看看SleepEx是怎么定义的.

DWORD WINAPI SleepEx(

    DWORD dwMillesconds,

    BOOL bAlertable);

这里主要说明第二个参数的用途:线程是否将自己置为可提醒状态.(在可提醒I/O中,当I/O完成时,系统将他们添加到线程APC队列中-回调函数不会立即被调用.如果我们想让其被调用需要将这个参数设置为TRUE).

本例并没有牵涉到这类问题,所以无论FALSE或者TRUE都无所谓.

如果我们只想要定义一个一次性定时器.可以参考如下代码:

  1. HANDLE hTimer = NULL;  
  2.   
  3. LARGE_INTEGER liDueTime;  
  4.   
  5.   liDueTime.QuadPart = -100000000;//10s  
  6.   
  7. hTimer = CreateWaitableTimer(NULL, TRUE,NULL);  
  8.   
  9.     if ( hTimer == NULL ) return;  
  10.   
  11.     if (!SetWaitableTimer(hTimer, &liDueTime, 1000, NULL, NULL, 0))  
  12.   
  13.     {   
  14.   
  15. CloseHandle(hTimer);  
  16.   
  17.         return;  
  18.   
  19. }  
  20.   
  21. clock_t c_beg = clock();  
  22.   
  23. if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0)  
  24.   
  25. {  
  26.   
  27. CloseHandle(hTimer);  
  28.   
  29. return ;  
  30.   
  31. }  
  32.   
  33. else  
  34.   
  35. {  
  36.   
  37. //操作  
  38.   
  39. }  
  40.   
  41. CloseHandle(hTimer);  

最后需要说明的一点是APC(异步调用过程)加入定时器中:

  1. VOID APIENTRY TimerAPCRoutine( PVOID pvArgToCompletionRoutine,DWORD dwTimerLowValue,DWORD dwTimerHighValue)  
  2.   
  3. {  
  4.   
  5. cout<<"high:"<<dwTimerHighValue<<"      low"<<dwTimerLowValue<<endl;  
  6.   
  7. }  
  8.   
  9. void main()  
  10.   
  11. {  
  12.   
  13. HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL );  
  14.   
  15. LARGE_INTEGER li;  
  16.   
  17. li.QuadPart = 0;  
  18.   
  19.   
  20. if( !SetWaitableTimer( hTimer,&li,1000,TimerAPCRoutine,NULL,FALSE ))  
  21.   
  22. {  
  23.   
  24. CloseHandle( hTimer );  
  25.   
  26. return;  
  27.   
  28. }  
  29.   
  30.   
  31. while ( 1 )  
  32.   
  33. {  
  34.   
  35. SleepEx( 1000,TRUE );  
  36.   
  37. }  
  38.   
  39. CloseHandle( hTimer );  
  40.   
  41. getchar();  
  42.   
  43. }  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值