c++中CreateEvent函数解析(1)
函數原型:
?
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, // SDBOOL bManualReset, // reset typeBOOL bInitialState, // initial stateLPCTSTR lpName // object name );?
?
lpEventAttributes:指向SECURITY_ATTRIBUTES結構體,此結構體決定函數的返回句柄是否可以讓子進程繼承。如果這個參數為NULL,這個句柄是不能繼承的。一般情況下,這個參數設置為NULL。
bManualReset:指定將創建的EVENT是自動復位還是手動復位。如果為TRUE,需要用ResetEvent(HANDLE)函數手動復位狀態為無信號,即一旦改EVENT被設置成有信號,則它會一直等到ResetEvent調用時才為無信號狀態。如果為FALSE,當一個有信號的等待線程被釋放后,系統會自動復位狀態為無信號狀態。
bInitialState:指定事件對象的初始狀態。如果為TRUE,初始狀態為有信號,否則為無信號。
lpName:? 事件對象的名稱,以字符串表示。名稱的長度受MAX_PATH的限制,名稱是大小寫敏感的。如果lpName匹配一個存在的命名的事件對象,函數將請求EVENT_ALL_ACCESS來訪問存在的對象。在這種情況下,bManualReset和bInitialState 被忽略,因為這兩個參數已經被存在的事件設置。如果lpEventAttributes參數不為NULL,這個參數可以決定是否句柄被繼承,但是它的安全描述(security-descriptor)成員被忽略。如果lpName 為NULL,創建一個沒有名稱的事件。如果lpName 匹配一個存在的semaphore, mutex, waitable timer, job或者file-mapping對象的名稱,函數調用失敗,GetLastError函數返回ERROR_INVALID_HANDLE。由于這些對象共享相同的命名空間,才導致這種情況的發生。
返回值:??? 函數返回句柄,該句柄具有EVENT_ALL_ACCESS權限去訪問新的事件對象,同時它可以在任何需要事件對象句柄的函數中使用。
??? 調用過程中的任何線程,都可以在一個等待函數中指定事件對象句柄。當指定的對象的狀態為有信號時,單對象等待函數(例如WaitForSingleObject)返回。對于多對象等待函數(例如WaitForMultipleObjects),可以指定為任意或所有指定的對象被置為有信號狀態。當等待函數返回時,等待線程將被釋放去繼續它的執行。?? 事件對象的初始狀態由bInitialState參數指定,用SetEvent函數可以設置對象為有信號狀態,用ResetEvent函數可以設置對象為無信號狀態。?? 當一個手動復原的事件對象的狀態被置為有信號狀態時,該對象將一直保持有信號狀態,直至明確調用ResetEvent函數將其置為無符號狀態。當事件對象被設置為有信號狀態時,任何數量的等待線程或者隨后等待的線程都會被釋放。
??? 當一個自動復原事件對象的狀態被設置為有信號狀態時,該對象一直保持有信號狀態,直至一個單等待線程被釋放;系統然后會自動重置對象到無信號狀態。???
多個進程可持有同一個事件對象的多個句柄,可以通過使用此對象來實現進程間的同步。下面的對象共享機制是可行的:
·在CreateEvent函數中,lpEventAttributes參數指定句柄可被繼承時,通過CreateProcess函數創建的子進程繼承的事件對象句柄。
·一個進程可以在DuplicateHandle函數中指定事件對象句柄,從而獲得一個復制的句柄,此句柄可以被其它進程使用。
? ??? ·一個進程可以在OpenEvent或CreateEvent函數中指定一個名字,從而獲得一個有名的事件對象句柄。(在調用OpenEvent或CreateEvent函數時,一個進程可以指定事件對象的名字。)
使用CloseHandle函數關閉句柄。當進程終止時,系統將自動關閉句柄。事件對象會被銷毀,當最后一個句柄被關閉。
?
二、c++CreateEvent函數在多線程中使用及實例
?
下面主要演示一下采用CreateEvent實現多線程。
例子很簡單,主要測試CreateEvent中bManualReset:和bInitialState參數的取值在線程調用中信號狀態的情況。
?
測試1:
bManualReset:TRUE
bInitialState:TRUE
CreateEvent(NULL, TRUE, TRUE, NULL); //使用手動重置為無信號狀態,初始化時有信號狀態
example.cpp
#include "iostream" #include "windows.h" using namespace std; DWORD WINAPI ThreadProc1(LPVOID lpParam); DWORD WINAPI ThreadProc2(LPVOID lpParam); HANDLE hEvent = NULL; HANDLE hThread1 = NULL; HANDLE hThread2 = NULL; int main(int argc, char *args[]) { hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)</span>; //使用手動重置為無信號狀態,初始化時有信號狀態 //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //當一個等待線程被釋放時,自動重置為無信號狀態,初始是有信號狀態 //if (SetEvent(hEvent)) //{ // cout << "setEvent 成功" <<endl; //} hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL); Sleep(200); hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL); Sleep(200); if ( NULL == hThread1) { cout <<"create thread fail!"; } //DWORD dCount = ResumeThread(hThread); //cout << LOWORD(dCount) << endl; return 0; } DWORD WINAPI ThreadProc1(LPVOID lpParam) { cout <<"in thread1@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<" thread1 signaled ! "<<endl; } cout <<"in thread1 --signal"<<endl; //SetEvent(hEvent); return 0; } DWORD WINAPI ThreadProc2(LPVOID lpParam) { cout <<"in thread2@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<"thread2 signaled ! "<<endl; } cout <<"in thread2--signal"<<endl; return 0; }
執行結果:
?
從結果中看,執行完線程1又執行了線程2.
由于hEvent = CreateEvent(NULL, TRUE, TRUE, NULL),使用手動重置為無信號狀態,初始化時有信號狀態
所以hEvent一直處于有信號狀態,無論是線程1釋放后,hEvent仍處于有信號狀態,所以線程2正常執行了。
?
測試2:
bManualReset:FALSE
bInitialState:TRUE
?
hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //當一個等待線程被釋放時,自動重置為無信號狀態,初始是有信號狀態
example2.cpp
?
?
#include "iostream" #include "windows.h" using namespace std; DWORD WINAPI ThreadProc1(LPVOID lpParam); DWORD WINAPI ThreadProc2(LPVOID lpParam); HANDLE hEvent = NULL; HANDLE hThread1 = NULL; HANDLE hThread2 = NULL; int main(int argc, char *args[]) { //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手動重置為無信號狀態,初始化時有信號狀態 hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); </span>//當一個等待線程被釋放時,自動重置為無信號狀態,初始是有信號狀態 //if (SetEvent(hEvent)) //{ // cout << "setEvent 成功" <<endl; //} hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL); Sleep(200); hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL); Sleep(200); if ( NULL == hThread1) { cout <<"create thread fail!"; } //DWORD dCount = ResumeThread(hThread); //cout << LOWORD(dCount) << endl; return 0; } DWORD WINAPI ThreadProc1(LPVOID lpParam) { cout <<"in thread1@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<" thread1 signaled ! "<<endl; } cout <<"in thread1 --signal"<<endl; //SetEvent(hEvent); return 0; } DWORD WINAPI ThreadProc2(LPVOID lpParam) { cout <<"in thread2@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<"thread2 signaled ! "<<endl; } cout <<"in thread2--signal"<<endl; return 0; }執行結果:
?
從執行結果中分析,執行了線程1,線程2一直在等待,直到主線程結束。
由于hEvent = CreateEvent(NULL, FALSE, TRUE, NULL),當一個等待線程被釋放時,自動重置為無信號狀態,初始是有信號狀態
初始執行線程1的時候,hEvent是有信號的,所以線程1正常執行;又由于bManualReset=FALSE,所以執行完線程1后,hEven
?
WaitForSingleObject(hEvent,INFINITE);
函數一直在等待hEvent變為有信號狀態,但是當主線程執行完,還沒等待到,線程2程序一直沒有走下去。
?
?
測試3:
bManualReset:TRUE
bInitialState:FALSE
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手動重置為無信號狀態,初始化時為無信號狀態
example3.cpp
#include "iostream" #include "windows.h" using namespace std; DWORD WINAPI ThreadProc1(LPVOID lpParam); DWORD WINAPI ThreadProc2(LPVOID lpParam); HANDLE hEvent = NULL; HANDLE hThread1 = NULL; HANDLE hThread2 = NULL; int main(int argc, char *args[]) { //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手動重置為無信號狀態,初始化時有信號狀態 //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //當一個等待線程被釋放時,自動重置為無信號狀態,初始是有信號狀態 hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手動重置為無信號狀態,初始化時為無信號狀態</span> //if (SetEvent(hEvent)) //{ // cout << "setEvent 成功" <<endl; //} hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL); Sleep(200); hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL); Sleep(200); if ( NULL == hThread1) { cout <<"create thread fail!"; } //DWORD dCount = ResumeThread(hThread); //cout << LOWORD(dCount) << endl; return 0; } DWORD WINAPI ThreadProc1(LPVOID lpParam) { cout <<"in thread1@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<" thread1 signaled ! "<<endl; } cout <<"in thread1 --signal"<<endl; //SetEvent(hEvent); return 0; } DWORD WINAPI ThreadProc2(LPVOID lpParam) { cout <<"in thread2@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<"thread2 signaled ! "<<endl; } cout <<"in thread2--signal"<<endl; return 0; }執行結果,可想而知,只能輸出:
in?thread1@!?
in?thread2@!?
因為初始為無信號狀態,所以hEvent一直處于無信號狀態,因此這兩個線程一直在等待,直到主線程結束。
?
修改:放開例子中的注釋部分:
if (SetEvent(hEvent))//設置信號為有信號狀態
{
cout << "setEvent 成功" <<endl;
}
執行結果:
?
可見,線程1和線程2都執行了。
因為調用SetEvent,事件變為有信號狀態,線程1執行;又由于線程1釋放后,hEvent仍舊處于有信號狀態,所以線程2也執行了。
?
再修改:在線程1中,添加ResetEvent(hEvent)(手動設置事件為無信號狀態),則線程2不會執行。
?
測試4:
bManualReset:FALSE
bInitialState:FALSE
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//線程釋放后自動重置為無信號狀態,初始化時為無信號狀態
example4.cpp
?
#include "iostream" #include "windows.h" using namespace std; DWORD WINAPI ThreadProc1(LPVOID lpParam); DWORD WINAPI ThreadProc2(LPVOID lpParam); HANDLE hEvent = NULL; HANDLE hThread1 = NULL; HANDLE hThread2 = NULL; int main(int argc, char *args[]) { //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手動重置為無信號狀態,初始化時有信號狀態 //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //當一個等待線程被釋放時,自動重置為無信號狀態,初始是有信號狀態 //hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手動重置為無信號狀態,初始化時為無信號狀態 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//使用手動重置為無信號狀態,初始化時為無信號狀態 if (SetEvent(hEvent)) { cout << "setEvent 成功" <<endl; } hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL); Sleep(200); hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL); Sleep(200); if ( NULL == hThread1) { cout <<"create thread fail!"; } //DWORD dCount = ResumeThread(hThread); //cout << LOWORD(dCount) << endl; return 0; } DWORD WINAPI ThreadProc1(LPVOID lpParam) { cout <<"in thread1@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<" thread1 signaled ! "<<endl; } cout <<"in thread1 --signal"<<endl; //SetEvent(hEvent); return 0; } DWORD WINAPI ThreadProc2(LPVOID lpParam) { cout <<"in thread2@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<"thread2 signaled ! "<<endl; } cout <<"in thread2--signal"<<endl; return 0; }?
?
?
由于調用SetEvent,hEvent為有信號狀態,線程1正常執行,又由于調用完線程1后,hEvent自動重置為無信號狀態,所以線程2只能在等待,直到主線程退出。
修改:線程1中的SetEvent(hEvent);的注釋去掉,再運行,則線程1和線程2 都會執行。
總結
以上是生活随笔為你收集整理的c++中CreateEvent函数解析(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MFC四种同步手段
- 下一篇: H.264的技术优势及其在H.323系统