CreateEvent、SetEvent、ResetEvent和WaitForSingleObject

來源:互聯網
上載者:User

標籤:createevent   setevent   resetevent   waitforsingleobject   

事件對象就像一個開關:它只有兩種狀態---開和關。當一個事件處於”開”狀態,我們稱其為”有訊號”,否則稱為”無訊號”。可以在一個線程的執行函數中建立一個事件對象,然後觀察它的狀態,如果是”無訊號”就讓該線程睡眠,這樣該線程佔用的CPU時間就比較少。

產生事件對象的函數如下:

(1)CreateEvent
函數原型:

HANDLE CreateEvent(   
    LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全屬性   
    BOOL bManualReset, // 複位方式   
    BOOL bInitialState, // 初始狀態   
    LPCTSTR lpName // 對象名稱   
); 

      該函數建立一個Event同步對象,如果CreateEvent調用成功的話,會返回新產生的對象的控制代碼,否則返回NULL。
      lpEventAttributes:一般為NULL  
      bManualReset:指定將事件對象建立成手動複原還是自動複原。如果是TRUE(手動),那麼就算等待線程處理了,必須用ResetEvent函數來手工才能將事件的狀態複原到無訊號狀態。如果設定為FALSE(自動),當事件被一個等待線程處理並釋放以後,系統會自動將事件狀態複原為無訊號狀態。所以兩者可用於不同的場合,自動複位的需要每次的事件訊號才會執行,而手動複位的則可以一直運行。
      bInitialState:指定事件對象的初始狀態。如果為TRUE,初始狀態為有訊號狀態;否則為無訊號狀態。
      lpName:指定事件的對象的名稱,在OpenEvent函數中可能使用。
      

       範例程式碼:// 建立一個有名的,不能被繼承的,手動複原,初始狀態是無訊號狀態的事件對象:
       Handle h = CreateEvent(NULL,TRUE,FALSE,“MyEvent”);

         一個Event被建立以後,可以用OpenEvent()API來獲得它的Handle,用CloseHandle()來關閉它,用SetEvent()或PulseEvent()來設定它使其有訊號,用ResetEvent()來使其無訊號,用WaitForSingleObject()或WaitForMultipleObjects()來等待其變為有訊號.。  

(2)SetEvent

函數原型:
BOOL WINAPI SetEvent(
      __in  HANDLE hEvent
);
設定事件的狀態為有標記。如果事件建立時是手工的,此事件將保持有標記直到調用ResetEvent。如果事件是自動的,此事件將保持有標記,直到一個線程被釋放,系統將設定事件的狀態為無標記。

(3)ResetEvent

函數原型:
BOOL ResetEvent(   
     HANDLE hEvent   
); 
hEvent 指向事件對象的控制代碼,由 CreateEvent or OpenEvent 函數返回。這個控制代碼需要擁有EVENT_MODIFY_STATE 存取權限。函數成功,返回非0值,否則返回0值,可以調用GetLastError得到錯誤的詳細資料。 
      這個函數用於手動重設事件對象。手動重設的對象線上程釋放後必須手動置為無訊號狀態。自動重設的事件對象在一個等待它成功的線程釋放後會自動變為無訊號狀態。 重設一個無訊號的事件對象沒有任何效果。

(4)WaitForSingleObject

函數原型:
DWORD WaitForSingleObject( 

      HANDLE hHandle, 

      DWORD dwMilliseconds

);
參數hHandle是一個事件的控制代碼,第二個參數dwMilliseconds是時間間隔。如果事件是有訊號狀態返回WAIT_OBJECT_0,如果事件超過dwMilliseconds值但事件還是無訊號狀態,則返回WAIT_TIMEOUT。之前線程會一直阻塞程式在該語句處。


舉例:

#include <windows.h>#include <iostream>#include <string>#include <vector>using namespace std;//通過事件得知另一個線程的內部狀態//例:線程內部有三種狀態:起床 吃飯 上班HANDLE getupHandle;HANDLE breakfastHandle;HANDLE workHandle;vector<string> stateTexts;DWORD WINAPI Worker(LPVOID n);int main(){stateTexts.reserve(3);//容器預留空間getupHandle = CreateEvent(NULL, TRUE, FALSE, NULL);//手動,無訊號breakfastHandle = CreateEvent(NULL, TRUE, FALSE, NULL);workHandle = CreateEvent(NULL, TRUE, FALSE, NULL);DWORD threadId;HANDLE threadHandle = CreateThread(NULL,0,Worker,//線程入口函數0,0,&threadId);WaitForSingleObject(getupHandle, INFINITE);cout << stateTexts[0] << endl;WaitForSingleObject(breakfastHandle, 3000);cout << stateTexts[1] << endl;WaitForSingleObject(workHandle, INFINITE);cout << stateTexts[2] << endl;CloseHandle(threadHandle);CloseHandle(getupHandle);CloseHandle(breakfastHandle);CloseHandle(workHandle);system("pause");}DWORD WINAPI Worker(LPVOID n){stateTexts.push_back("GetUp");SetEvent(getupHandle);stateTexts.push_back("Breakfast");ResetEvent(breakfastHandle);stateTexts.push_back("Work");SetEvent(workHandle);return 0;}
運行結果:

先顯示 GetUp,等待3000ms後顯示Breakfast,接著馬上顯示Work

由於getupHandle和workHandle是設定為有訊號的,它們的WaitForSingleObject直接有返回值

breakfastHandle設定為無訊號的,它的WaitForSingleObject要等待定時完成才有返回值

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.