WaitForSingleObject()

         轉載自:http://yijiuzai.blog.163.com/blog/static/103756727201043073124192/

 

      用戶模式的線程同步機制效率高,如果需要考慮線程同步問題,應該首先考慮用戶模式的線程同步方法。

  但是,用戶模式的線程同步有限制,對於多個進程之間的線程同步,用戶模式的線程同步方法無能爲力。這時,只能考慮使用內核模式。

  Windows提供了許多內核對象來實現線程的同步。對於線程同步而言,這些內核對象有兩個非常重要的狀態:“已通知”狀態,“未通知”狀態(也有翻譯爲:受信狀態,未受信狀態)。Windows提供了幾種內核對象可以處於已通知狀態和未通知狀態:進程、線程、作業、文件、控制檯輸入/輸出/錯誤流、事件、等待定時器、信號量、互斥對象。

  你可以通知一個內核對象,使之處於“已通知狀態”,然後讓其他等待在該內核對象上的線程繼續執行。你可以使用Windows提供的API函數,等待函數來等待某一個或某些內核對象變爲已通知狀態。

  你可以使用WaitForSingleObject函數來等待一個內核對象變爲已通知狀態:

DWORD WaitForSingleObject(
HANDLE hObject, //指明一個內核對象的句柄
DWORD dwMilliseconds); //等待時間
  該函數需要傳遞一個內核對象句柄,該句柄標識一個內核對象,如果該內核對象處於未通知狀態,則該函數導致線程進入阻塞狀態;如果該內核對象處於已通知狀態,則該函數立即返回WAIT_OBJECT_0。第二個參數指明瞭需要等待的時間(毫秒),可以傳遞INFINITE指明要無限期等待下去。如果等待超時,該函數返回WAIT_TIMEOUT。如果該函數失敗,返回WAIT_FAILED。可以通過下面的代碼來判斷:

DWORD dw = WaitForSingleObject(hProcess, 5000); //等待一個進程結束
switch (dw)
{
case WAIT_OBJECT_0:
// hProcess所代表的進程在5秒內結束
break;

case WAIT_TIMEOUT:
// 等待時間超過5秒
break;

case WAIT_FAILED:
// 函數調用失敗,比如傳遞了一個無效的句柄
break;
}
  
還可以使用WaitForMulitpleObjects函數來等待多個內核對象變爲已通知狀態:

DWORD WaitForMultipleObjects(
DWORD dwCount, //等待的內核對象個數
CONST HANDLE* phObjects, //一個存放被等待的內核對象句柄的數組
BOOL bWaitAll, //是否等到所有內核對象爲已通知狀態後才返回
DWORD dwMilliseconds); //等待時間
  該函數的第一個參數指明等待的內核對象的個數,可以是0到MAXIMUM_WAIT_OBJECTS(64)中的一個值。phObjects參數是一個存放等待的內核對象句柄的數組。bWaitAll參數如果爲TRUE,則只有當等待的所有內核對象爲已通知狀態時函數才返回,如果爲FALSE,則只要一個內核對象爲已通知狀態,則該函數返回。第四個參數和WaitForSingleObject中的dwMilliseconds參數類似。

  該函數失敗,返回WAIT_FAILED;如果超時,返回WAIT_TIMEOUT;如果bWaitAll參數爲TRUE,函數成功則返回WAIT_OBJECT_0,如果bWaitAll爲FALSE,函數成功則返回值指明是哪個內核對象收到通知。

  可以如下使用該函數:

HANDLE h[3]; //句柄數組

//三個進程句柄
h[0] = hProcess1;
h[1] = hProcess2;
h[2] = hProcess3;

DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000); //等待3個進程結束

switch (dw)
{
case WAIT_FAILED:
// 函數呼叫失敗
break;

case WAIT_TIMEOUT:
// 超時
break;

case WAIT_OBJECT_0 + 0:
// h[0](hProcess1)所代表的進程結束
break;

case WAIT_OBJECT_0 + 1:
// h[1](hProcess2)所代表的進程結束
break;

case WAIT_OBJECT_0 + 2:
// h[2](hProcess3)所代表的進程結束
break;
}
  
你也可以同時通知一個內核對象,同時等待另一個內核對象,這兩個操作以原子的方式進行:

DWORD SignalObjectAndWait(
HANDLE hObjectToSignal, //通知的內核對象
HANDLE hObjectToWaitOn, //等待的內核對象
DWORD dwMilliseconds, //等待的時間
BOOL bAlertable); //與IO完成端口有關的參數,暫不討論
  該函數在內部使得hObjectToSignal參數所指明的內核對象變成已通知狀態,同時等待hObjectToWaitOn參數所代表的內核對象。dwMilliseconds參數的用法與WaitForSingleObject函數類似。
  該函數返回如下:WAIT_OBJECT_0,WAIT_TIMEOUT,WAIT_FAILED,WAIT_IO_COMPLETION。

  等你需要通知一個互斥內核對象並等待一個事件內核對象的時候,可以這麼寫:

ReleaseMutex(hMutex);
WaitForSingleObject(hEvent, INFINITE);
  可是,這樣的代碼不是以原子的方式來操縱這兩個內核對象。因此,可以更改如下:

SignalObjectAndWait(hMutex, hEvent, INFINITE, FALSE);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章