兩個等待函數 一個單線程,一個多線程。
等待函數可使線程自願進入等待狀態,直到一個特定的核心對象變為已通知狀態為止。(FangSH註:如果核心對象沒有變為通知即線程永遠等待下去。)這些等待函數中最常用的是WaitForSingleObject :
DWORD WaitForSingleObject(HANDLEhObject,
DWORD dwMilliseconds);
第一個參數hObject標識一個能夠支援被通知/未通知的核心對象(前面列出的任何一種對象都適用)。(FangSH注:控制代碼)
第二個參數dwMilliseconds指明等待對象變為已通知狀態所需的等待時間。(時間間隔以毫秒為單位,INFINITE表示直到等到hHandle為已通知狀態)。傳遞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;
}
上面這個代碼告訴系統,在特定的進程終止運行之前,或者在5000ms時間結束之前,調用線程不應該變為可調度狀態。因此,如果進程終止運行,那麼這個函數調用將在不到5000ms的時間內返回,如果進程尚未終止運行,那麼它在大約5000ms時間內返回。注意,不要為d wMillisecond傳遞0。如果傳遞了0,WaitForSingleObject函數將總是立即返回。
WaitForSingleObject的傳回值能夠指明調用線程為什麼再次變為可調度狀態。
如果線程等待的對象變為已通知狀態,那麼傳回值是WAIT_OBJECT_0。
如果設定的逾時已經到期,則傳回值是WA I T_ TIMEOUT。
如果將一個錯誤的值(如一個無效控制代碼)傳遞給Wa itForSingleObject,那麼傳回值將是WA IT_FAILED(若要瞭解詳細資料,可調用GetLastError)。
WaitForMultipleObjects調用線程同時查看若干個核心對象的已通知狀態:
DWORD WaitForMultipleObjects(DWORDdwCount,
CONST HANDLE* phObjects,
BOOL fWaitAll,
DWORD dwMilliseconds);
dwCount參數用於指明想要讓函數查看的核心對象的數量。這個值必須在1與MAXIMUM _WA I T_OBJECTS(在Windows標頭檔中定義為64)之間。
phObjects參數是指向核心物件控點的數組的指標。
可以以兩種不同的方式來使用WaitForMultipleObjects函數。
一種方式是讓線程進入等待狀態,直到指定核心對象中的任何一個變為已通知狀態。
另一種方式是讓線程進入等待狀態,直到所有指定的核心對象都變為已通知狀態。
fWaitAll參數告訴該函數,你想要讓它使用何種方式。如果為該參數傳遞TRUE,那麼在所有對象變為已通知狀態之前,該函數將不允許調用線程運行。
dwMilliseconds參數的作用與它在WaitForSingleObject中的作用完全相同。如果在等待的時候規定的時間到了,那麼該函數無論如何都會返回。同樣,通常為該參數傳遞INFINITE,但是在編寫代碼時應該小心,以避免出現死結情況。
WaitForSingleObject函數的傳回值告訴調用線程,為什麼它會被重新調度。
可能的傳回值是WA IT_FAILED和WAIT_TIMEOUT,這兩個值的作用是很清楚的。
如果為fWaitAll參數傳TRUE,同時所有對象均變為已通知狀態,那麼傳回值是WAIT_OBJECT_0。
如果為fWaitAll傳遞FA LSE,那麼一旦任何一個對象變為已通知狀態,該函數便返回。
在這種情況下,你可能想要知道哪個對象變為已通知狀態。傳回值是WAIT_OBJECT_0與(WA IT_OBJECT_0 + dwCount - 1)之間的一個值。
換句話說,如果傳回值不是WA IT_TIMEOUT,也不是WAIT_FA ILED,那麼應該從傳回值中減去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參數傳遞FA LSE,WaitForSingleObjects就從索引0開始向上對控制代碼數組進行掃描,同時已通知的第一個對象終止等待狀態。這可能產生一些你不希望有的結果。例如,通過將3個進程控制代碼傳遞給該函數,你的線程就會等待3個子進程終止運行。如果數組中索引為0的進程終止運行,WaitForSingleObject就會返回。這時該線程就可以做它需要的任何事情,然後迴圈反覆,等待另一個進程終止運行。如果該線程傳遞相同的3個控制代碼,該函數立即再次返回WAIT_OBJECT_0。除非刪除已經收到通知的控制代碼,否則代碼就無法正確地運行。
FangSH 2010-12-29