Wait 関数
Wait 関数 スレッドが独自の実行をブロックできるようにします。 待機関数は、指定された条件が満たされるまで戻りません。 wait 関数の種類によって、使用される条件のセットが決まります。 待機関数が呼び出されると、待機条件が満たされているかどうかを確認します。 条件が満たされていない場合、呼び出し元のスレッドは、待機条件の条件が満たされるか、指定されたタイムアウト間隔が経過するまで待機状態に入ります。
- 単一オブジェクト待機関数 の
- 複数オブジェクト待機関数の の
- アラート可能な待機関数 を する
- 登録済み待機関数 を する
- アドレス で待機中の
- 待機関数とタイムアウト間隔
- 待機関数と同期オブジェクト の
- 待機関数の と Windows の作成
単一オブジェクト待機関数
SignalObjectAndWait、waitForSingleObject、および waitForSingleObjectEx関数には、1 つの同期オブジェクトへのハンドルが必要です。 これらの関数は、次のいずれかが発生すると返されます。
- 指定されたオブジェクトがシグナル状態です。
- タイムアウト間隔が経過します。 タイムアウト間隔を INFINITE に設定して、待機がタイムアウトしないことを指定できます。
SignalObjectAndWait 関数を使用すると、呼び出し元スレッドはオブジェクトの状態をアトミックにシグナル通知に設定し、別のオブジェクトの状態がシグナル通知に設定されるのを待ちます。
複数オブジェクト待機関数
WaitForMultipleObjects、waitForMultipleObjectsEx、MsgWaitForMultipleObjects、および MsgWaitForMultipleObjectsEx 関数を使用すると、呼び出し元のスレッドは、1 つ以上の同期オブジェクト ハンドルを含む配列を指定できます。 これらの関数は、次のいずれかが発生すると返されます。
- 指定したオブジェクトのいずれかの状態が signaled に設定されているか、すべてのオブジェクトの状態が signaled に設定されています。 関数呼び出しで 1 つまたはすべての状態を使用するかどうかを制御します。
- タイムアウト間隔が経過します。 タイムアウト間隔を INFINITE に設定して、待機がタイムアウトしないことを指定できます。
MsgWaitForMultipleObjects および MsgWaitForMultipleObjectsEx 関数を使用すると、オブジェクト ハンドル配列に入力イベント オブジェクトを指定できます。 これは、スレッドの入力キューで待機する入力の種類を指定するときに行われます。 たとえば、スレッド MsgWaitForMultipleObjects を使用して、指定したオブジェクトの状態がシグナル通知に設定され、スレッドの入力キューにマウス入力が使用可能になるまで、その実行をブロックできます。 スレッドは、GetMessage または PeekMessageAを使用するか、PeekMessageW関数をして入力を取得できます。
すべてのオブジェクトの状態がシグナル通知に設定されるのを待機している場合、これらの複数オブジェクト関数は、すべてのオブジェクトの状態がシグナル通知に設定されるまで、指定されたオブジェクトの状態を変更しません。 たとえば、ミューテックス オブジェクトの状態は通知できますが、呼び出し元のスレッドは、配列で指定された他のオブジェクトの状態もシグナル通知に設定されるまで所有権を取得しません。 それまでの間、他のスレッドがミューテックス オブジェクトの所有権を取得し、その状態を非署名に設定する場合があります。
1 つのオブジェクトの状態がシグナル通知に設定されるのを待つ場合、これらの複数オブジェクト関数は、オブジェクトの 1 つがシグナル通知されるまで、インデックス 0 で始まる順序で配列内のハンドルをチェックします。 複数のオブジェクトがシグナル通知された場合、関数はオブジェクトがシグナル通知された配列内の最初のハンドルのインデックスを返します。
Alertable Wait 関数
MsgWaitForMultipleObjectsEx、SignalObjectAndWait、WaitForMultipleObjectsEx、および waitForSingleObjectEx関数は、必要に応じてアラート可能な待機操作 実行できる他の待機関数とは異なります。 警告可能な待機操作では、指定された条件が満たされたときに関数は戻ることができますが、システムが待機中のスレッドによって実行するために I/O 完了ルーチンまたは APC をキューに入れた場合にも戻ることができます。 警告可能な待機操作と I/O 完了ルーチンの詳細については、「同期と重複入力と出力の」を参照してください。 APC の詳細については、「非同期プロシージャ 呼び出し」を参照してください。
登録済み待機関数
RegisterWaitForSingleObject 関数は、待機操作が スレッド プールからのスレッドによって実行されるという点で、他の待機関数とは異なります。 指定された条件が満たされると、コールバック関数はスレッド プールのワーカー スレッドによって実行されます。
既定では、登録済みの待機操作は複数待機操作です。 UnregisterWaitEx 関数を呼び出して操作を取り消すまで、イベントが通知されるたびにタイマーがリセットされます (またはタイムアウト間隔が経過します)。 待機操作を 1 回だけ実行するように指定するには、registerWaitForSingleObjectの dwFlags パラメーターを WT_EXECUTEONLYONCEに設定します。
スレッドが API を使用する関数を呼び出す場合は、RegisterWaitForSingleObject の dwFlags パラメーターを WT_EXECUTEINPERSISTENTTHREADに設定します。
アドレスの待機中
スレッドは、WaitOnAddress 関数を使用して、ターゲット アドレスの値が望ましくない値から他の値に変化するのを待機できます。 これにより、スレッドは、スレッドが望ましくない値をキャプチャするが、スレッドが待機する前に値が変更されたときに発生する可能性がある同期の問題をスピンまたは処理することなく、値の変更を待機できます。
WaitOnAddress は、1 つの待機スレッドをウェイクアップするか、WakeByAddressAllをしてすべての待機中のスレッドをスリープ解除 WakeByAddressSingle を呼び出すことによって、ターゲット値を変更するコードが変更を通知したときに返されます。 WaitOnAddress でタイムアウト間隔 指定され、スレッドがウェイク関数を呼び出さない場合、タイムアウト間隔が経過すると関数は戻ります。 タイムアウト間隔が指定されていない場合、スレッドは無期限に待機します。
待機関数とタイムアウト間隔
指定されたタイムアウト間隔の精度は、システム クロックの解像度によって異なります。 システム クロックは、一定のレートで "ティック" します。 タイムアウト間隔がシステム クロックの解像度より小さい場合、待機は指定した時間よりも短い時間でタイムアウトする可能性があります。 タイムアウト間隔が 1 ティックより大きく、2 未満の場合、待機は 1 と 2 ティックの間の任意の場所にできます。
待機関数のタイムアウト間隔の精度を高めるには、timeGetDevCaps 関数を呼び出して、サポートされている最小タイマー解決を決定し、タイマー解決を最小に設定する timeBeginPeriod 関数を指定します。 timeBeginPeriod 呼び出す場合は注意が必要です。頻繁な呼び出しは、システム クロック、システム電源の使用状況、スケジューラに大きな影響を与える可能性があります。 timeBeginPeriodを呼び出す場合は、アプリケーションの早い段階で 1 回呼び出し、アプリケーションの最後に timeEndPeriod 関数を呼び出してください。
待機関数と同期オブジェクト
待機関数は、一部の種類の 同期オブジェクトの状態を変更できます。 変更は、シグナル状態によって関数が戻される原因となったオブジェクトに対してのみ行われます。 待機関数は、同期オブジェクトの状態を次のように変更できます。
- セマフォ オブジェクトの数は 1 ずつ減少し、セマフォの数が 0 の場合、セマフォの状態は非署名に設定されます。
- ミューテックス、自動リセット イベント、および変更通知オブジェクトの状態は、非署名に設定されます。
- 同期タイマーの状態は、非署名に設定されます。
- 手動リセット イベント、手動リセット タイマー、プロセス、スレッド、およびコンソール入力オブジェクトの状態は、待機関数の影響を受けません。
待機関数と Windows の作成
直接または間接的にウィンドウを作成する待機関数とコードを使用する場合は、注意する必要があります。 スレッドがウィンドウを作成する場合は、メッセージを処理する必要があります。 メッセージ ブロードキャストは、システム内のすべてのウィンドウに送信されます。 タイムアウト間隔のない待機関数を使用するスレッドがある場合、システムはデッドロックします。 ウィンドウを間接的に作成するコードの 2 つの例は、DDE と CoInitialize 関数です。 したがって、ウィンドウを作成するスレッドがある場合は、他の待機関数ではなく、MsgWaitForMultipleObjectsexMsgWaitForMultipleObjectsEx使用します。