可等待定时器问题:
1. 需要的函数:CreateWaitableTimer,SetWaitableTimer.前者创建一个可等待定时器句柄,后者设置等待定时器触发的条件.我们可以多次调用SetWaitableTimer来重置可等待定时器.重置后之前的定时器将关闭.
2. 主要看两段代码:
代码一:(这段代码在网上出现的概率是较大的)
- 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);
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的时间几乎是可以忽略不计的.)
这样就引入了核心编程里面作者的代码:
代码二:
- 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);
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都无所谓.
如果我们只想要定义一个一次性定时器.可以参考如下代码:
- 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);
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(异步调用过程)加入定时器中:
- 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();
- }
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();
}
所有评论(0)