一個自動重置事件的對象,WaitForSingleObject在等待成功以后會把事件對象設置為未觸發狀態(馬上調用ResetEvent()函數),而手動設置事件對象不會有這個副作用。
#include <iostream> #include <process.h> #include <windows.h> #include <string> using std::cout; using std::endl; using std::string; const int num=10; int count; HANDLE ThreadEvent; unsigned __stdcall ThreadFun(void* par); int main() { //創建內核事件對象(自動重置,未激活狀態) ThreadEvent=CreateEvent(NULL,FALSE,FALSE,NULL); HANDLE handles[num]; for(int i=0;i<num;++i) { handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0); WaitForSingleObject(ThreadEvent,INFINITE); //自動激活狀態的事件,WaitForSingleObject帶來的副作用就是會自己調用ResetEvent()將事件設置為未激活 } for(int i=0;i<num;++i) CloseHandle(handles[i]); CloseHandle(ThreadEvent);//關閉內核事件對象 system("PAUSE"); return 0; } unsigned __stdcall ThreadFun(void* par) { cout<<"count:"<<++count<<endl; SetEvent(ThreadEvent);//設置事件為激活狀態 return 0; }
把事件對象設置為手動重置,就需要我們手動重置事件狀態。
int main() { //創建內核事件對象(手動重置,未激活狀態) ThreadEvent=CreateEvent(NULL,TRUE,FALSE,NULL); HANDLE handles[num]; for(int i=0;i<num;++i) { handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0); WaitForSingleObject(ThreadEvent,INFINITE); //手動激活的事件,WaitForSingleObject不會重置事件為未激活。 ResetEvent(ThreadEvent);//手動重置事件對象為未激活狀態 } for(int i=0;i<num;++i) CloseHandle(handles[i]); CloseHandle(ThreadEvent);//關閉內核事件對象 system("PAUSE"); return 0; }
上面代碼內核事件對象為手動重置,所以在WaitForSingleObject以后需要手動調用ResetEvent(),如果把ResetEvent(ThreadEvent);注釋掉,那么所以等待線程都會被觸發,導致同步失敗。
for(int i=0;i<num;++i) { handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0); WaitForSingleObject(ThreadEvent,INFINITE); //手動激活的事件,WaitForSingleObject不會重置事件為未激活。 //ResetEvent(ThreadEvent);//后面的線程都會很順利的執行,事件對象一直為激活狀態 }
線程執行同步失敗,輸出混亂,可以將num變量設置大點,這樣更加容易出現混亂輸出。
本文版權歸kennyMc和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。