原文鏈接:http://m.shnenglu.com/wangjt/archive/2008/02/01/42312.html
Event即事件是一種用于進(jìn)行線程/進(jìn)程間同步的對(duì)象,事件有置位和復(fù)位兩種狀態(tài),當(dāng)線程通過(guò)waiting functions等待Event對(duì)象置位時(shí)該線程將進(jìn)入阻塞狀態(tài),當(dāng)該Event對(duì)象被置位或等待超時(shí)后,等待的線程將恢復(fù)執(zhí)行。Event可以用在一個(gè)線程要等待其它線程時(shí)。
可以使用CreateEvent創(chuàng)建Event對(duì)象
HANDLE WINAPI CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName
);
lpEventAttributes用于指定Event對(duì)象的安全屬性,包括句柄是否可被子進(jìn)程繼承和對(duì)象的安全描述符。可設(shè)置NULL取默認(rèn)安全屬性。
bManualReset表明Event對(duì)象是否需要手動(dòng)復(fù)位。如果該參數(shù)為TRUE,則Event對(duì)象需要通過(guò)ResetEvent函數(shù)手動(dòng)復(fù)位。如果該參數(shù)為FALSE,則Event被創(chuàng)建為自動(dòng)復(fù)位的Event,任何等待的線程被恢復(fù)執(zhí)行后,該Event將被系統(tǒng)自動(dòng)復(fù)位。打個(gè)比方,如果有10個(gè)線程在等待一個(gè)Event,這時(shí)將Event置位,如果這是個(gè)手動(dòng)復(fù)位Event,那么這10個(gè)線程將被依次喚醒直到通過(guò)ResetEvent調(diào)用將該Event復(fù)位;如果Event為自動(dòng)復(fù)位Event,那么10個(gè)線程中的第一個(gè)被喚醒后Event被自動(dòng)復(fù)位,其它線程將繼續(xù)等待。
bInitialState參數(shù)表明Event對(duì)象被創(chuàng)建后默認(rèn)是否置位。
lpName參數(shù)是Event的名字,可以為空表明將創(chuàng)建匿名Event。
CreateEvent函數(shù)在調(diào)用成功后返回Event句柄。如果同名Event已經(jīng)存在,則返回這個(gè)已經(jīng)存在了的Event的句柄,此時(shí)調(diào)用GetLastError函數(shù)將返回 ERROR_ALREADY_EXISTS。
還可以通過(guò)OpenEvent打開(kāi)一個(gè)已經(jīng)創(chuàng)建的非匿名Event
HANDLE WINAPI OpenEvent(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
在創(chuàng)建或打開(kāi)了Event對(duì)象之后,可以使用SetEvent和ResetEvent函數(shù)來(lái)置位或復(fù)位一個(gè)Event對(duì)象。
BOOL WINAPI SetEvent(
HANDLE hEvent
);
BOOL WINAPI ResetEvent(
HANDLE hEvent
);
要等待一個(gè)或多個(gè)Event對(duì)象置位可以使用wait functions。
簡(jiǎn)單示例,一個(gè)線程不停讀取用戶輸入并放入message列表,另一個(gè)線程模擬將message發(fā)送出去,如果沒(méi)有消息,則發(fā)送線程處于阻塞狀態(tài)等待,一旦有消息錄入,輸入線程將event置位,發(fā)送線程即被激活并逐個(gè)發(fā)送消息。
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <list>
#include <string>
using namespace std;
#ifdef _UNICODE
typedef wstring tstring;
#define tcout wcout
#define tcin wcin
#else
typedef string tstring;
#define tcout cout
#define tcin cin
#endif /* _UNICODE */
typedef list<tstring> StringList;
HANDLE hMutex = NULL;
HANDLE hEvent = NULL;
HANDLE hSendThread = NULL;
StringList messages;
bool isRunning;
DWORD WINAPI SendThreadProc(LPVOID lpThreadParameter)
{
DWORD dw;
while(isRunning)
{
dw = WaitForSingleObject(hEvent, INFINITE);
if(dw != WAIT_OBJECT_0)
{
tcout << _T("Wait error.") << endl;
return -1;
}
dw = WaitForSingleObject(hMutex, INFINITE);
if(WAIT_OBJECT_0 != dw && WAIT_ABANDONED != dw)
{
tcout << _T("Wait error.") << endl;
return -2;
}
StringList list(messages);
messages.clear();
ReleaseMutex(hMutex);
for(StringList::iterator i = list.begin(); i != list.end(); i++)
{
Sleep(1000); //休眠1秒模擬發(fā)送所耗時(shí)間
tcout << _T("/* Send Message:") << *i << _T(" */");
}
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
hMutex = CreateMutex(NULL, FALSE, NULL);
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
isRunning = true;
hSendThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendThreadProc, NULL, 0, NULL);
while(isRunning)
{
tstring s;
tcin >> s;
if(s == _T("quit"))
{
isRunning = true;
break;
}
DWORD dw = WaitForSingleObject(hMutex, INFINITE);
if(WAIT_OBJECT_0 != dw && WAIT_ABANDONED != dw)
{
tcout << _T("Wait error.") << endl;
return -1;
}
messages.push_back(s);
ReleaseMutex(hMutex);
SetEvent(hEvent);
}
CloseHandle(hMutex);
CloseHandle(hEvent);
CloseHandle(hSendThread);
return 0;
}