由于多線程中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,如需轉載請自行聯系原作者