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();

}