c++中CreateEvent函数解析(1)
函數(shù)原型:
?
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, // SDBOOL bManualReset, // reset typeBOOL bInitialState, // initial stateLPCTSTR lpName // object name );?
?
lpEventAttributes:指向SECURITY_ATTRIBUTES結(jié)構(gòu)體,此結(jié)構(gòu)體決定函數(shù)的返回句柄是否可以讓子進(jìn)程繼承。如果這個(gè)參數(shù)為NULL,這個(gè)句柄是不能繼承的。一般情況下,這個(gè)參數(shù)設(shè)置為NULL。
bManualReset:指定將創(chuàng)建的EVENT是自動(dòng)復(fù)位還是手動(dòng)復(fù)位。如果為TRUE,需要用ResetEvent(HANDLE)函數(shù)手動(dòng)復(fù)位狀態(tài)為無(wú)信號(hào),即一旦改EVENT被設(shè)置成有信號(hào),則它會(huì)一直等到ResetEvent調(diào)用時(shí)才為無(wú)信號(hào)狀態(tài)。如果為FALSE,當(dāng)一個(gè)有信號(hào)的等待線程被釋放后,系統(tǒng)會(huì)自動(dòng)復(fù)位狀態(tài)為無(wú)信號(hào)狀態(tài)。
bInitialState:指定事件對(duì)象的初始狀態(tài)。如果為TRUE,初始狀態(tài)為有信號(hào),否則為無(wú)信號(hào)。
lpName:? 事件對(duì)象的名稱,以字符串表示。名稱的長(zhǎng)度受MAX_PATH的限制,名稱是大小寫(xiě)敏感的。如果lpName匹配一個(gè)存在的命名的事件對(duì)象,函數(shù)將請(qǐng)求EVENT_ALL_ACCESS來(lái)訪問(wèn)存在的對(duì)象。在這種情況下,bManualReset和bInitialState 被忽略,因?yàn)檫@兩個(gè)參數(shù)已經(jīng)被存在的事件設(shè)置。如果lpEventAttributes參數(shù)不為NULL,這個(gè)參數(shù)可以決定是否句柄被繼承,但是它的安全描述(security-descriptor)成員被忽略。如果lpName 為NULL,創(chuàng)建一個(gè)沒(méi)有名稱的事件。如果lpName 匹配一個(gè)存在的semaphore, mutex, waitable timer, job或者file-mapping對(duì)象的名稱,函數(shù)調(diào)用失敗,GetLastError函數(shù)返回ERROR_INVALID_HANDLE。由于這些對(duì)象共享相同的命名空間,才導(dǎo)致這種情況的發(fā)生。
返回值:??? 函數(shù)返回句柄,該句柄具有EVENT_ALL_ACCESS權(quán)限去訪問(wèn)新的事件對(duì)象,同時(shí)它可以在任何需要事件對(duì)象句柄的函數(shù)中使用。
??? 調(diào)用過(guò)程中的任何線程,都可以在一個(gè)等待函數(shù)中指定事件對(duì)象句柄。當(dāng)指定的對(duì)象的狀態(tài)為有信號(hào)時(shí),單對(duì)象等待函數(shù)(例如WaitForSingleObject)返回。對(duì)于多對(duì)象等待函數(shù)(例如WaitForMultipleObjects),可以指定為任意或所有指定的對(duì)象被置為有信號(hào)狀態(tài)。當(dāng)?shù)却瘮?shù)返回時(shí),等待線程將被釋放去繼續(xù)它的執(zhí)行。?? 事件對(duì)象的初始狀態(tài)由bInitialState參數(shù)指定,用SetEvent函數(shù)可以設(shè)置對(duì)象為有信號(hào)狀態(tài),用ResetEvent函數(shù)可以設(shè)置對(duì)象為無(wú)信號(hào)狀態(tài)。?? 當(dāng)一個(gè)手動(dòng)復(fù)原的事件對(duì)象的狀態(tài)被置為有信號(hào)狀態(tài)時(shí),該對(duì)象將一直保持有信號(hào)狀態(tài),直至明確調(diào)用ResetEvent函數(shù)將其置為無(wú)符號(hào)狀態(tài)。當(dāng)事件對(duì)象被設(shè)置為有信號(hào)狀態(tài)時(shí),任何數(shù)量的等待線程或者隨后等待的線程都會(huì)被釋放。
??? 當(dāng)一個(gè)自動(dòng)復(fù)原事件對(duì)象的狀態(tài)被設(shè)置為有信號(hào)狀態(tài)時(shí),該對(duì)象一直保持有信號(hào)狀態(tài),直至一個(gè)單等待線程被釋放;系統(tǒng)然后會(huì)自動(dòng)重置對(duì)象到無(wú)信號(hào)狀態(tài)。???
多個(gè)進(jìn)程可持有同一個(gè)事件對(duì)象的多個(gè)句柄,可以通過(guò)使用此對(duì)象來(lái)實(shí)現(xiàn)進(jìn)程間的同步。下面的對(duì)象共享機(jī)制是可行的:
·在CreateEvent函數(shù)中,lpEventAttributes參數(shù)指定句柄可被繼承時(shí),通過(guò)CreateProcess函數(shù)創(chuàng)建的子進(jìn)程繼承的事件對(duì)象句柄。
·一個(gè)進(jìn)程可以在DuplicateHandle函數(shù)中指定事件對(duì)象句柄,從而獲得一個(gè)復(fù)制的句柄,此句柄可以被其它進(jìn)程使用。
? ??? ·一個(gè)進(jìn)程可以在OpenEvent或CreateEvent函數(shù)中指定一個(gè)名字,從而獲得一個(gè)有名的事件對(duì)象句柄。(在調(diào)用OpenEvent或CreateEvent函數(shù)時(shí),一個(gè)進(jìn)程可以指定事件對(duì)象的名字。)
使用CloseHandle函數(shù)關(guān)閉句柄。當(dāng)進(jìn)程終止時(shí),系統(tǒng)將自動(dòng)關(guān)閉句柄。事件對(duì)象會(huì)被銷毀,當(dāng)最后一個(gè)句柄被關(guān)閉。
?
二、c++CreateEvent函數(shù)在多線程中使用及實(shí)例
?
下面主要演示一下采用CreateEvent實(shí)現(xiàn)多線程。
例子很簡(jiǎn)單,主要測(cè)試CreateEvent中bManualReset:和bInitialState參數(shù)的取值在線程調(diào)用中信號(hào)狀態(tài)的情況。
?
測(cè)試1:
bManualReset:TRUE
bInitialState:TRUE
CreateEvent(NULL, TRUE, TRUE, NULL); //使用手動(dòng)重置為無(wú)信號(hào)狀態(tài),初始化時(shí)有信號(hào)狀態(tài)
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>; //使用手動(dòng)重置為無(wú)信號(hào)狀態(tài),初始化時(shí)有信號(hào)狀態(tài) //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //當(dāng)一個(gè)等待線程被釋放時(shí),自動(dòng)重置為無(wú)信號(hào)狀態(tài),初始是有信號(hào)狀態(tài) //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; }
執(zhí)行結(jié)果:
?
從結(jié)果中看,執(zhí)行完線程1又執(zhí)行了線程2.
由于hEvent = CreateEvent(NULL, TRUE, TRUE, NULL),使用手動(dòng)重置為無(wú)信號(hào)狀態(tài),初始化時(shí)有信號(hào)狀態(tài)
所以hEvent一直處于有信號(hào)狀態(tài),無(wú)論是線程1釋放后,hEvent仍處于有信號(hào)狀態(tài),所以線程2正常執(zhí)行了。
?
測(cè)試2:
bManualReset:FALSE
bInitialState:TRUE
?
hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //當(dāng)一個(gè)等待線程被釋放時(shí),自動(dòng)重置為無(wú)信號(hào)狀態(tài),初始是有信號(hào)狀態(tài)
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); //使用手動(dòng)重置為無(wú)信號(hào)狀態(tài),初始化時(shí)有信號(hào)狀態(tài) hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); </span>//當(dāng)一個(gè)等待線程被釋放時(shí),自動(dòng)重置為無(wú)信號(hào)狀態(tài),初始是有信號(hào)狀態(tài) //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; }執(zhí)行結(jié)果:
?
從執(zhí)行結(jié)果中分析,執(zhí)行了線程1,線程2一直在等待,直到主線程結(jié)束。
由于hEvent = CreateEvent(NULL, FALSE, TRUE, NULL),當(dāng)一個(gè)等待線程被釋放時(shí),自動(dòng)重置為無(wú)信號(hào)狀態(tài),初始是有信號(hào)狀態(tài)
初始執(zhí)行線程1的時(shí)候,hEvent是有信號(hào)的,所以線程1正常執(zhí)行;又由于bManualReset=FALSE,所以執(zhí)行完線程1后,hEven
?
WaitForSingleObject(hEvent,INFINITE);
函數(shù)一直在等待hEvent變?yōu)橛行盘?hào)狀態(tài),但是當(dāng)主線程執(zhí)行完,還沒(méi)等待到,線程2程序一直沒(méi)有走下去。
?
?
測(cè)試3:
bManualReset:TRUE
bInitialState:FALSE
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手動(dòng)重置為無(wú)信號(hào)狀態(tài),初始化時(shí)為無(wú)信號(hào)狀態(tài)
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); //使用手動(dòng)重置為無(wú)信號(hào)狀態(tài),初始化時(shí)有信號(hào)狀態(tài) //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //當(dāng)一個(gè)等待線程被釋放時(shí),自動(dòng)重置為無(wú)信號(hào)狀態(tài),初始是有信號(hào)狀態(tài) hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手動(dòng)重置為無(wú)信號(hào)狀態(tài),初始化時(shí)為無(wú)信號(hào)狀態(tài)</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; }執(zhí)行結(jié)果,可想而知,只能輸出:
in?thread1@!?
in?thread2@!?
因?yàn)槌跏紴闊o(wú)信號(hào)狀態(tài),所以hEvent一直處于無(wú)信號(hào)狀態(tài),因此這兩個(gè)線程一直在等待,直到主線程結(jié)束。
?
修改:放開(kāi)例子中的注釋部分:
if (SetEvent(hEvent))//設(shè)置信號(hào)為有信號(hào)狀態(tài)
{
cout << "setEvent 成功" <<endl;
}
執(zhí)行結(jié)果:
?
可見(jiàn),線程1和線程2都執(zhí)行了。
因?yàn)檎{(diào)用SetEvent,事件變?yōu)橛行盘?hào)狀態(tài),線程1執(zhí)行;又由于線程1釋放后,hEvent仍舊處于有信號(hào)狀態(tài),所以線程2也執(zhí)行了。
?
再修改:在線程1中,添加ResetEvent(hEvent)(手動(dòng)設(shè)置事件為無(wú)信號(hào)狀態(tài)),則線程2不會(huì)執(zhí)行。
?
測(cè)試4:
bManualReset:FALSE
bInitialState:FALSE
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//線程釋放后自動(dòng)重置為無(wú)信號(hào)狀態(tài),初始化時(shí)為無(wú)信號(hào)狀態(tài)
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); //使用手動(dòng)重置為無(wú)信號(hào)狀態(tài),初始化時(shí)有信號(hào)狀態(tài) //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //當(dāng)一個(gè)等待線程被釋放時(shí),自動(dòng)重置為無(wú)信號(hào)狀態(tài),初始是有信號(hào)狀態(tài) //hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手動(dòng)重置為無(wú)信號(hào)狀態(tài),初始化時(shí)為無(wú)信號(hào)狀態(tài) hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//使用手動(dòng)重置為無(wú)信號(hào)狀態(tài),初始化時(shí)為無(wú)信號(hào)狀態(tài) 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; }?
?
?
由于調(diào)用SetEvent,hEvent為有信號(hào)狀態(tài),線程1正常執(zhí)行,又由于調(diào)用完線程1后,hEvent自動(dòng)重置為無(wú)信號(hào)狀態(tài),所以線程2只能在等待,直到主線程退出。
修改:線程1中的SetEvent(hEvent);的注釋去掉,再運(yùn)行,則線程1和線程2 都會(huì)執(zhí)行。
總結(jié)
以上是生活随笔為你收集整理的c++中CreateEvent函数解析(1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: MFC四种同步手段
- 下一篇: C++中socket编程