DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

可等待定时器问题:

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. CloseHandle( hTimer ); 
  12.  
  13. return
  14.  
  15.  
  16. while ( 1 ) 
  17.  
  18.  
  19. //clock_t c_beg = clock();  
  20.  
  21. WaitForSingleObject( hTimer,INFINITE ); 
  22.  
  23. //clock_t end = clock() - c_beg;  
  24.  
  25. //cout<<"time:"<<end<<endl;  
  26.  
  27. cout<<"定时器触发了...\n"
  28.  
  29.  
  30. CloseHandle(hTimer); 
HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL );

LARGE_INTEGER li;

li.QuadPart = 0;


if( !SetWaitableTimer( hTimer,&li,1000,NULL,NULL,FALSE ))

{

CloseHandle( hTimer );

return;

}

while ( 1 )

{

//clock_t c_beg = clock();

WaitForSingleObject( hTimer,INFINITE );

//clock_t end = clock() - c_beg;

//cout<<"time:"<<end<<endl;

cout<<"定时器触发了...\n";

}

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. CloseHandle( hTimer ); 
  12.  
  13. return
  14.  
  15.  
  16.  
  17. while ( 1 ) 
  18.  
  19.  
  20. clock_t c_beg = clock(); 
  21.  
  22. SleepEx( 1000,TRUE );//这里并没有使用WaitForSingleObject,而是使用SleepEx  
  23.  
  24. clock_t end = clock() - c_beg; 
  25.  
  26. cout<<"time:"<<end<<endl; 
  27.  
  28.  
  29. CloseHandle(hTimer); 
HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL );

LARGE_INTEGER li;

li.QuadPart = 0;


if( !SetWaitableTimer( hTimer,&li,1000,NULL,NULL,FALSE ))

{

CloseHandle( hTimer );

return;

}


while ( 1 )

{

clock_t c_beg = clock();

SleepEx( 1000,TRUE );//这里并没有使用WaitForSingleObject,而是使用SleepEx

clock_t end = clock() - c_beg;

cout<<"time:"<<end<<endl;

}

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. clock_t c_beg = clock(); 
  21.  
  22. if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0) 
  23.  
  24.  
  25. CloseHandle(hTimer); 
  26.  
  27. return
  28.  
  29.  
  30. else 
  31.  
  32.  
  33. //操作  
  34.  
  35.  
  36. CloseHandle(hTimer); 
HANDLE hTimer = NULL;

LARGE_INTEGER liDueTime;

  liDueTime.QuadPart = -100000000;//10s

hTimer = CreateWaitableTimer(NULL, TRUE,NULL);

    if ( hTimer == NULL ) return;

    if (!SetWaitableTimer(hTimer, &liDueTime, 1000, NULL, NULL, 0))

    { 

CloseHandle(hTimer);

        return;

}

clock_t c_beg = clock();

if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0)

{

CloseHandle(hTimer);

return ;

}

else

{

//操作

}

CloseHandle(hTimer);

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

  1. VOID APIENTRY TimerAPCRoutine( PVOID pvArgToCompletionRoutine,DWORD dwTimerLowValue,DWORD dwTimerHighValue) 
  2.  
  3.  
  4. cout<<"high:"<<dwTimerHighValue<<"      low"<<dwTimerLowValue<<endl; 
  5.  
  6.  
  7. void main() 
  8.  
  9.  
  10. HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL ); 
  11.  
  12. LARGE_INTEGER li; 
  13.  
  14. li.QuadPart = 0; 
  15.  
  16.  
  17. if( !SetWaitableTimer( hTimer,&li,1000,TimerAPCRoutine,NULL,FALSE )) 
  18.  
  19.  
  20. CloseHandle( hTimer ); 
  21.  
  22. return
  23.  
  24.  
  25.  
  26. while ( 1 ) 
  27.  
  28.  
  29. SleepEx( 1000,TRUE ); 
  30.  
  31.  
  32. CloseHandle( hTimer ); 
  33.  
  34. getchar(); 
  35.  
VOID APIENTRY TimerAPCRoutine( PVOID pvArgToCompletionRoutine,DWORD dwTimerLowValue,DWORD dwTimerHighValue)

{

cout<<"high:"<<dwTimerHighValue<<"      low"<<dwTimerLowValue<<endl;

}

void main()

{

HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL );

LARGE_INTEGER li;

li.QuadPart = 0;


if( !SetWaitableTimer( hTimer,&li,1000,TimerAPCRoutine,NULL,FALSE ))

{

CloseHandle( hTimer );

return;

}


while ( 1 )

{

SleepEx( 1000,TRUE );

}

CloseHandle( hTimer );

getchar();

}
posted on 2013-05-07 15:49  DoubleLi  阅读(1031)  评论(0编辑  收藏  举报