CreateWaitableTimerとSetWaitableTimerの詳細
待機タイマの問題:
1.必要な関数:CreateWaitableTimer,SetWaitableTimer.前者は待機可能なタイマハンドルを作成する、後者は待機タイマのトリガ条件を設定する.SetWaitableTimerを複数回呼び出して待機タイマをリセットすることができます.リセット前のタイマーがオフになります.
2.主に2つのコードを見ます.
コード1:(このコードがネット上に現れる確率は大きい)
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<<" ...
";
}
CloseHandle(hTimer);
上記のコメントのコードを離すと、次のことがわかります.
◆最初の2つのタイマの出発過程は「不安定」である(すなわち、それらにかかる時間は1秒ではない.
◆安定した後でも、タイマーの差は1 sではなく1000(ミリ秒)程度であることはおかしい.
2番目の問題がclockの実行による誤差であるとすると、1番目の問題は説明できない.△実はclockの時間はほとんど無視できる.
コアプログラミングの著者のコードを導入しました
コード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();
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);
ここでは主に2番目のパラメータの用途を説明する:スレッドが自分をアラーム可能な状態にするかどうか.(アラーム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);
最後に説明したいのは、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();
}