天天看點

WaitForSingleObject 和 WaitForMultipleObjects函數 (讓線程挂起等待事件)

WaitForSingleObject 和 WaitForMultipleObjects:

1.WaitForSingleObject

  等待函數可使線程自願進入等待狀态,直到一個特定的核心對象變為已通知狀态為止。這些等待函數中最常用的是WaitForSingleObject:    DWORD WaitForSingleObject(HANDLE hObject, DWORD dwMilliseconds); 當線程調用該函數時,第一個參數hObject辨別一個能夠支援被通知/未通 知的核心對象。第二個參數dwMilliseconds.允許該線程指明,為了等待該對象變為已通知狀态,它将等待多長時間。調用下面這個函數将告訴系 統,調用函數準備等待到hProcess句柄辨別的程序終止運作為止: WaitForSingleObject(hProcess, INFINITE); 第二個參數告訴系統,調用線程願意永遠等待下去(無限時間量),直到該程序終止運作。 通常情況下, INFINITE是作為第二個參數傳遞給WaitForSingleObject的,不過也可以傳遞任何一個值(以毫秒計算)。順便說一下, INFINITE已經定義為0xFFFFFFFF(或-1)。當然,傳遞INFINITE有些危險。如果對象永遠不變為已通知狀态,那麼調用線程永遠不會 被喚醒,它将永遠處于死鎖狀态, 不過,它不會浪費寶貴的CPU時間。 下面是如何用一個逾時值而不是INFINITE來調用WaitForSingleObject的例子: DWORD dw = WaitForSingleObject(hProcess, 5000); switch(dw) {      case WAIT_OBJECT_0:            // The process terminated.            break;      case WAIT_TIMEOUT:            // The process did not terminate within 5000 milliseconds.            break;      case WAIT_FAILED:            // Bad call to function (invalid handle?)            break; } 上面這個代碼告訴系統,在特定的程序終止運作之前,或者在5 0 0 0 m s時間結束之前,調用線程不應該變為可排程狀态。是以,如果程序終止運作,那麼這個 函數調用将在不到5000ms的時間内傳回,如果程序尚未終止運作,那麼它在大約5000ms時間内傳回。注意,不能為dwMilliseconds傳遞0。如果傳遞了0,WaitForSingleObject函數将總是立即傳回。

2.WaitForMultipleObjects

WaitForSingleObject的傳回值能夠指明調用線程為什麼再次變為可排程狀态。如果線程等待的對象變為已通知狀态,那麼傳回值是 WAIT_OBJECT_0。如果設定的逾時已經到期,則傳回值是WAIT_TIMEOUT。如果将一個錯誤的值(如一個無效句柄)傳遞給 WaitForSingleObject,那麼傳回值将是WAIT_FAILED(若要了解詳細資訊,可調用GetLastError)。 下面這個函數WaitForMultipleObjects與WaitForSingleObject函數很相似,差別在于它允許調用線程同時檢視若幹個核心對象的已通知狀态: DWORD WaitForMultipleObjects(DWORD dwCount,      CONST HANDLE* phObjects,      BOOL fWaitAll,      DWORD dwMilliseconds); dwCount參數用于指明想要讓函數檢視的核心對象的數量。這個值必須在1與MAXIMUM_WAIT_OBJECTS(在Windows頭檔案中定義為64)之間。phObjects參數是指向核心對象句柄的數組的指針。 可以以兩種不同的方式來使用WaitForMultipleObjects函數。 一種方式是讓線程進入等待狀态,直到指定核心對象中的任何一個變為已通知狀态。 另一種方式是讓線程進入等待狀态,直到所有指定的核心對象都變為已通知狀态。fWaitAll參數告訴該函數,你想要讓它使用何種方式。如果為該參數傳遞TRUE,那麼在所有對象變為已通知狀态之前,該函數将不允許調用線程運作。 dwMilliseconds參數的作用與它在WaitForSingleObject中的作用完全相同。如果在等待的時候規定的時間到了,那麼該函數無論如何都會傳回。同樣,通常為該參數傳遞INFINITE,但是在編寫代碼時應該小心,以避免出現死鎖情況。 WaitForMultipleObjects函數的傳回值告訴調用線程,為 什麼它會被重新排程。可能的傳回值是WAIT_FAILED和WAIT_TIMEOUT,這兩個值的作用是很清楚的。如果fWaitAll參數傳遞 TRUE,同時所有對象均變為已通知狀态,那麼傳回值是WAIT_OBJECT_0。如果為fWaitAll傳遞FALSE,那麼一旦任何一個對象變為已 通知狀态,該函數便傳回。在這種情況下,你可能想要知道哪個對象變為已通知狀态。傳回值是WAIT_OBJECT_0 與(WAIT_OBJECT_0 +  dwCount-1)之間的一個值。換句話說,如果傳回值不是WAIT_TIMEOUT,也不是WAIT_FAILED,那麼應該從傳回值中減去 WAIT_OBJECT_0。産生的數字是作為第二個參數傳遞給WaitForMultipleObjects的句柄數組中的索引。該索引說明哪個對象變 為已通知狀态。 下面是說明這一情況的一些示例代碼: HANDLE h[3]; h[0] = hProcess1; h[1] = hProcess2; h[2] = hProcess3; DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000); switch(dw) {      case WAIT_FAILED:            // Bad call to function (invalid handle?)            break;      case WAIT_TIMEOUT:            // None of the objects became signaled within 5000 milliseconds.            break;      case WAIT_OBJECT_0 + 0:            // The process identified by h[0] (hProcess1) terminated.            break;      case WAIT_OBJECT_0 + 1:            // The process identified by h[1] (hProcess2) terminated.            break;      case WAIT_OBJECT_0 + 2:            // The process identified by h[2] (hProcess3) terminated.            break; } 如果為fWaitAll參數傳遞 FALSE,WaitForMultipleObjects就從索引0開始向上對句柄數組進行掃描,同時已通知的第一個對象終止等待狀态。這可能産生一些 你不希望有的結果。例如,通過将3個程序句柄傳遞給該函數,你的線程就會等待3個子程序終止運作。如果數組中索引為0的程序終止運 行,WaitForMultipleObjects就會傳回。這時該線程就可以做它需要的任何事情,然後循環反複,等待另一個程序終止運作。如果該線程傳 遞相同的3個句柄,該函數立即再次傳回WAIT_OBJECT_0。除非删除已經收到通知的句柄,否則代碼就無法正确地運作。