等候函式
Wait 函式 允許線程封鎖自己的執行。 等候函式不會傳回,直到符合指定的準則為止。 wait 函式的類型會決定所使用的準則集。 呼叫等候函式時,它會檢查是否已符合等候準則。 如果條件尚未符合,則呼叫線程會進入等候狀態,直到符合等候準則的條件或指定的超時時間間隔經過為止。
- 單一物件 Wait Functions
- Multiple-object Wait Functions
- 可警示的等候函式
- 已註冊的等候函式
- 等候位址
- 等候函式和逾時間隔
- Wait 函式和同步處理物件
- Wait 函式和建立 Windows
單一物件 Wait 函式
SignalObjectAndWait、WaitForSingleObject和 WaitForSingleObjectEx 函式需要一個同步處理物件的句柄。 當發生下列其中一項時,這些函式會傳回:
- 指定的物件處於訊號狀態。
- 逾時間隔經過。 逾時間隔可以設定為 INFINITE,以指定等候不會逾時。
SignalObjectAndWait 函式可讓呼叫線程以不可部分完成的方式將對象的狀態設定為已發出訊號,並等候另一個對象的狀態設定為訊號。
多物件 Wait 函式
WaitForMultipleObjects、WaitForMultipleObjectsEx、MsgWaitForMultipleObjects和 MsgWaitForMultipleObjectsEx 函式可讓呼叫線程指定包含一或多個同步處理物件句柄的陣列。 當發生下列其中一項時,這些函式會傳回:
- 任何一個指定物件的狀態都會設定為已發出訊號,或所有物件的狀態已設定為已發出訊號。 您可以控制函式調用中是否要使用一或所有狀態。
- 逾時間隔經過。 逾時間隔可以設定為 INFINITE,以指定等候不會逾時。
MsgWaitForMultipleObjects 和 MsgWaitForMultipleObjectsEx 函式可讓您在物件句柄數位中指定輸入事件物件。 當您指定要在線程輸入佇列中等候的輸入類型時,就會完成此動作。 例如,線程可以使用 MsgWaitForMultipleObjects 來封鎖其執行,直到指定的對象狀態已設定為已發出訊號,且線程的輸入佇列中有可用的滑鼠輸入。 線程可以使用 GetMessage 或 PeekMessageA 或 PeekMessageW 函式來擷取輸入。
等候所有物件的狀態設定為已發出訊號時,這些多物件函式不會修改指定物件的狀態,直到設定所有物件的狀態才會發出訊號。 例如,Mutex 物件的狀態可以發出訊號,但呼叫線程在陣列中指定的其他物件狀態也設定為已發出訊號之前,不會取得擁有權。 同時,其他一些線程可能會取得 Mutex 物件的擁有權,藉此將其狀態設定為未簽署。
等候將單一物件的狀態設定為訊號時,這些多物件函式會檢查陣列中的句柄,從索引 0 開始,直到其中一個物件收到訊號為止。 如果多個物件收到訊號,函式會傳回陣列中對象已發出訊號之第一個句柄的索引。
可警示的等候函式
MsgWaitForMultipleObjectsEx、SignalObjectAndWait、WaitForMultipleObjectsEx和 WaitForSingleObjectEx 函式不同,因為它們可以選擇性地執行 可警示的等候作業。 在可警示的等候作業中,函式可以在符合指定條件時傳回,但如果系統佇列 I/O 完成例程或 APC 供等候線程執行,則函式也可以傳回。 如需可警示等候作業和 I/O 完成例程的詳細資訊,請參閱 同步處理和重疊輸入和輸出。 如需 APC 的詳細資訊,請參閱 異步過程呼叫。
已註冊的等候函式
RegisterWaitForSingleObject 函式不同於其他等候函式,因為等候作業是由 線程集區線程執行的。 符合指定的條件時,回呼函式是由線程集區的背景工作線程執行。
根據預設,已註冊的等候作業是多重等候作業。 系統會在每次發出事件訊號時重設定時器(或逾時間隔經過),直到您呼叫 UnregisterWaitEx 函式來取消作業為止。 若要指定應該只執行一次等候作業,請將 registerWaitForSingleObject 的 dwFlags 參數設定為 WT_EXECUTEONLYONCE。
如果線程呼叫使用 APC 的函式,請將 registerWaitForSingleObject 的 dwFlags 參數設定為 WT_EXECUTEINPERSISTENTTHREAD。
等候位址
線程可以使用 WaitOnAddress 函式,等候目標位址的值從某些不想要的值變更為任何其他值。 這可讓線程等候值變更,而不需要微調或處理線程擷取不想要的值,但在線程可以等候之前變更值時可能發生的同步處理問題。
WaitOnAddress 傳回修改目標值的程式代碼會呼叫 WakeByAddressSingle 來喚醒單一等候線程,或 WakeByAddressAll 來喚醒所有等候的線程。 如果使用 WaitOnAddres s 指定逾時間隔,且沒有線程呼叫喚醒函式,則當超時時間間隔經過時,函式會傳回。 如果未指定逾時間隔,線程會無限期等候。
等候函式和逾時間隔
指定超時時間間隔的精確度取決於系統時鐘的解析度。 系統時鐘會以固定速率「刻度」。 如果逾時間隔小於系統時鐘的解析度,則等候時間可能會少於指定的時間長度。 如果逾時間隔大於一個刻度,但小於兩個刻度,則等候可以是介於一到兩個刻度之間的任何位置,依此計算。
若要增加等候函式的超時時間間隔精確度,請呼叫 timeGetDevCaps 函式,以判斷支援的最小定時器解析度和 timeBeginPeriod 函式,將定時器解析度設定為最小值。 呼叫 timeBeginPeriod時請小心,因為頻繁的呼叫可能會大幅影響系統時鐘、系統電源使用量和排程器。 如果您呼叫 timeBeginPeriod,請在應用程式早期呼叫它一次,並確定在應用程式結尾呼叫 timeEndPeriod 函式。
等候函式和同步處理物件
等候函式可以修改某些類型 同步處理物件的狀態,。 修改只會針對發出訊號狀態導致函式傳回的物件或物件進行修改。 等候函式可以修改同步處理物件的狀態,如下所示:
- 旗號物件的計數會減少一個,如果信號計數為零,則信號的狀態會設定為非對齊。
- Mutex、自動重設事件和變更通知物件的狀態會設定為非ignaled。
- 同步處理定時器的狀態會設定為未簽署。
- 手動重設事件、手動重設定時器、進程、線程和控制台輸入物件的狀態不會受到等候函式的影響。
等候函式和建立 Windows
使用直接或間接建立視窗的等候函式和程式代碼時,您必須小心。 如果線程建立任何視窗,它就必須處理訊息。 訊息廣播會傳送至系統中的所有視窗。 如果您有線程使用沒有超時時間間隔的等候函式,系統將會死結。 間接建立視窗的程式代碼範例有 DDE 和 CoInitialize 函式。 因此,如果您有建立視窗的線程,請使用 MsgWaitForMultipleObjects 或 MsgWaitForMultipleObjectsEx,而不是其他等候函式。