Wait 函式

等候函式 允許執行緒封鎖自己的執行。 等候函式不會傳回,直到符合指定的準則為止。 等候函式的類型會決定使用的準則集。 呼叫等候函式時,它會檢查是否已符合等候準則。 如果不符合準則,則呼叫執行緒會進入等候狀態,直到符合等候準則的條件或指定的逾時間隔經過為止。

單一物件 Wait Functions

SignalObjectAndWaitWaitForSingleObjectWaitForSingleObjectEx函式需要一個同步處理物件的控制碼。 當發生下列其中一項時,這些函式會傳回:

  • 指定的物件處於訊號狀態。
  • 逾時間隔經過。 逾時間隔可以設定為 INFINITE ,以指定等候不會逾時。

SignalObjectAndWait函式可讓呼叫執行緒以不可部分完成的方式將物件的狀態設定為已發出訊號,並等候另一個物件的狀態設定為已發出訊號。

多物件 Wait Functions

WaitForMultipleObjectsWaitForMultipleObjectsExMsgWaitForMultipleObjectsMsgWaitForMultipleObjectsEx函式可讓呼叫執行緒指定包含一或多個同步處理物件控制碼的陣列。 當發生下列其中一項時,這些函式會傳回:

  • 任何一個指定物件的狀態都會設定為已發出訊號,或所有物件的狀態已設定為已發出訊號。 您可以控制函式調用中是否會使用一或所有狀態。
  • 逾時間隔經過。 逾時間隔可以設定為 INFINITE ,以指定等候不會逾時。

MsgWaitForMultipleObjectsMsgWaitForMultipleObjectsEx函式可讓您在物件控制碼陣列中指定輸入事件物件。 當您指定要線上程輸入佇列中等候的輸入類型時,就會完成此作業。 例如,執行緒可以使用 MsgWaitForMultipleObjects 來封鎖其執行,直到指定的物件狀態設定為已發出訊號,且執行緒的輸入佇列中有可用的滑鼠輸入。 執行緒可以使用GetMessagePeekMessageA 或 PeekMessageW函式來擷取輸入。

等候所有物件的狀態設定為已發出訊號時,這些多物件函式不會修改指定物件的狀態,直到所有物件的狀態都已設定訊號為止。 例如,可以發出 mutex 物件的狀態,但呼叫執行緒在陣列中指定的其他物件狀態也設定為已發出訊號之前,呼叫執行緒不會取得擁有權。 同時,某些其他執行緒可能會取得 mutex 物件的擁有權,藉此將其狀態設定為非簽署狀態。

等候單一物件的狀態設定為已發出訊號時,這些多物件函式會檢查陣列中的控制碼,從索引 0 開始,直到收到其中一個物件的訊號為止。 如果多個物件收到訊號,函式會傳回陣列中物件已發出訊號的第一個控制碼索引。

可警示的等候函式

MsgWaitForMultipleObjectsExSignalObjectAndWaitWaitForMultipleObjectsExWaitForSingleObjectEx函式與其他等候函式不同,因為它們可以選擇性地執行可警示的等候作業。 在可警示的等候作業中,函式可以在符合指定的條件時傳回,但如果系統佇列 I/O 完成常式或 APC 供等候執行緒執行,也可以傳回。 如需可警示的等候作業和 I/O 完成常式的詳細資訊,請參閱 同步處理和重迭的輸入和輸出。 如需 APC 的詳細資訊,請參閱 非同步程序呼叫

已註冊的等候函式

RegisterWaitForSingleObject函式與其他等候函式不同,因為等候作業是由執行緒集區中的執行緒執行。 符合指定的條件時,回呼函式是由執行緒集區中的背景工作執行緒執行。

根據預設,已註冊的等候作業是多等候作業。 系統會在每次發出事件訊號時重設計時器 (或逾時間隔會經過) ,直到您呼叫 UnregisterWaitEx 函式來取消作業為止。 若要指定應該只執行一次等候作業,請將RegisterWaitForSingleObjectdwFlags參數設定為WT_EXECUTEONLYONCE

如果執行緒呼叫使用 APC 的函式,請將RegisterWaitForSingleObjectdwFlags參數設定為WT_EXECUTEINPERSISTENTTHREAD

等候位址

執行緒可以使用 WaitOnAddress 函式,等候目標位址的值從某些不想要的值變更為任何其他值。 這可讓執行緒等候值變更,而不需要微調或處理執行緒擷取不想要的值時可能發生的同步處理問題,但值會線上程可以等候之前變更。

WaitOnAddress 會在修改目標值的程式碼呼叫 WakeByAddressSingle 以喚醒單一等候執行緒或 WakeByAddressAll 來喚醒所有等候執行緒,以發出變更訊號時傳回。 如果使用 WaitOnAddress 指定逾時間隔,而且沒有線程呼叫喚醒函式,則當逾時間隔經過時,函式會傳回。 如果未指定逾時間隔,執行緒會無限期等候。

等候函式和逾時間隔

指定逾時間隔的精確度取決於系統時鐘的解析度。 系統時鐘會以固定速率「刻度」。 如果逾時間隔小於系統時鐘的解析度,則等候可能會逾時少於指定的時間長度。 如果逾時間隔大於一個刻度,但小於兩個刻度,則等候可以位於一到兩個刻度之間,依此類傳。

若要增加等候函式的逾時間隔精確度,請呼叫 timeGetDevCaps 函式來判斷支援的最小計時器解析度和 timeBeginPeriod 函式,將計時器解析度設定為最小值。 呼叫 timeBeginPeriod時請小心,因為頻繁的呼叫可能會大幅影響系統時鐘、系統電源使用量和排程器。 如果您呼叫 timeBeginPeriod,請在應用程式中提早呼叫它一次,並確定在應用程式的結尾呼叫 timeEndPeriod 函式。

等候函式和同步處理物件

等候函式可以修改某些同步 處理物件類型的狀態。 修改只會針對發出訊號狀態導致函式傳回的物件或物件進行修改。 等候函式可以修改同步處理物件的狀態,如下所示:

  • 旗號物件的計數會減少一個,如果旗號的計數是零,則旗號的狀態會設定為非簽署。
  • Mutex、自動重設事件和變更通知物件的狀態會設定為非ignaled。
  • 同步處理計時器的狀態會設定為非簽署。
  • 手動重設事件、手動重設計時器、進程、執行緒和主控台輸入物件的狀態不會受到等候函式的影響。

等候函式和建立 Windows

使用直接或間接建立視窗的等候函式和程式碼時,您必須小心。 如果執行緒建立任何視窗,則必須處理訊息。 訊息廣播會傳送至系統中的所有視窗。 如果您有使用等候函式且沒有逾時間隔的執行緒,系統將會死結。 間接建立視窗的程式碼範例包括 DDE 和 CoInitialize 函式。 因此,如果您有建立視窗的執行緒,請使用 MsgWaitForMultipleObjectsMsgWaitForMultipleObjectsEx,而不是其他等候函式。