天天看點

C++多線程Event方法使用及執行個體(簡單彙總)

由于多線程中event方法平時很少用到,以前偶爾用下也是臨時到網上搜下代碼,沒有細細去了解,是以用完沒幾天就忘記了,今天又再次遇到需要event的問題,是以覺得有必要學習并整理下,下面是我在學習過程中百度到的兩篇文章,反正我是學明白了,希望也能幫助到大家。

c++中CreateEvent函數解析

HANDLE CreateEvent(

LPSECURITY_ATTRIBUTES lpEventAttributes,

BOOL bManualReset, 

BOOL bInitialState,

LPCSTR lpName

);

bManualReset:TRUE,使用ResetEvent()手動重置為無信号狀态;FALSE,當一個等待線程被釋放時,自動重置狀态為無信号狀态。

bInitialState:指定事件對象的初始狀态,當TRUE,初始狀态為有信号狀态;當FALSE,初始狀态為無信号狀态。

下面主要示範一下采用CreateEvent實作多線程。

例子很簡單,主要測試CreateEvent中bManualReset:和bInitialState參數的取值線上程調用中信号狀态的情況。

測試1:

bManualReset:TRUE

bInitialState:TRUE

CreateEvent(NULL, TRUE, TRUE, NULL); //使用手動重置為無信号狀态,初始化時有信号狀态

example.cpp

#include "iostream"

#include "windows.h"

usingnamespace 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[])  

{  

    <span style="color:#ff0000;">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);  

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);

DWORD WINAPI ThreadProc2(LPVOID lpParam)  

    cout <<"in thread2@!"<<endl;  

        cout <<"thread2 signaled ! "<<endl;  

    cout <<"in thread2--signal"<<endl;  

執行結果: 

從結果中看,執行完線程1又執行了線程2.

由于hEvent = CreateEvent(NULL, TRUE, TRUE, NULL),使用手動重置為無信号狀态,初始化時有信号狀态

是以hEvent一直處于有信号狀态,無論是線程1釋放後,hEvent仍處于有信号狀态,是以線程2正常執行了。

測試2:

bManualReset:FALSE

hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //當一個等待線程被釋放時,自動重置為無信号狀态,初始是有信号狀态

example2.cpp

//hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手動重置為無信号狀态,初始化時有信号狀态

    <span style="color:#ff0000;">hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); </span>//當一個等待線程被釋放時,自動重置為無信号狀态,初始是有信号狀态

從執行結果中分析,執行了線程1,線程2一直在等待,直到主線程結束。

由于hEvent = CreateEvent(NULL, FALSE, TRUE, NULL),當一個等待線程被釋放時,自動重置為無信号狀态,初始是有信号狀态

初始執行線程1的時候,hEvent是有信号的,是以線程1正常執行;又由于bManualReset=FALSE,是以執行完線程1後,hEvent自動重置為無信号狀态,是以線上程2中,

WaitForSingleObject(hEvent,INFINITE);  

函數一直在等待hEvent變為有信号狀态,但是當主線程執行完,還沒等待到,線程2程式一直沒有走下去。 

測試3:

bInitialState:FALSE

hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手動重置為無信号狀态,初始化時為無信号狀态

example3.cpp

    <span style="color:#ff0000;">hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手動重置為無信号狀态,初始化時為無信号狀态</span>

執行結果,可想而知,隻能輸出:

in thread1@!  

in thread2@!  

因為初始為無信号狀态,是以hEvent一直處于無信号狀态,是以這兩個線程一直在等待,直到主線程結束。 

修改:放開例子中的注釋部分:

if (SetEvent(hEvent))//設定信号為有信号狀态

{

cout << "setEvent 成功" <<endl;

}

執行結果:

可見,線程1和線程2都執行了。

因為調用SetEvent,事件變為有信号狀态,線程1執行;又由于線程1釋放後,hEvent仍舊處于有信号狀态,是以線程2也執行了。

再修改:線上程1中,添加ResetEvent(hEvent)(手動設定事件為無信号狀态),則線程2不會執行。

測試4:

hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//線程釋放後自動重置為無信号狀态,初始化時為無信号狀态

example4.cpp

//hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手動重置為無信号狀态,初始化時為無信号狀态

    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//使用手動重置為無信号狀态,初始化時為無信号狀态

if (SetEvent(hEvent))  

        cout << "setEvent 成功" <<endl;  

由于調用SetEvent,hEvent為有信号狀态,線程1正常執行,又由于調用完線程1後,hEvent自動重置為無信号狀态,是以線程2隻能在等待,直到主線程退出。

修改:線程1中的SetEvent(hEvent);的注釋去掉,再運作,則線程1和線程2 都會執行。

本文轉自 我不會抽煙 51CTO部落格,原文連結:http://blog.51cto.com/zhouhongyu1989/1225702,如需轉載請自行聯系原作者

繼續閱讀