原文鏈接:http://www.shnenglu.com/wangjt/archive/2008/02/01/42312.html
Event即事件是一種用于進行線程/進程間同步的對象,事件有置位和復位兩種狀態,當線程通過waiting functions等待Event對象置位時該線程將進入阻塞狀態,當該Event對象被置位或等待超時后,等待的線程將恢復執行。Event可以用在一個線程要等待其它線程時。
可以使用CreateEvent創建Event對象
HANDLE WINAPI CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName
);
lpEventAttributes用于指定Event對象的安全屬性,包括句柄是否可被子進程繼承和對象的安全描述符??稍O置NULL取默認安全屬性。
bManualReset表明Event對象是否需要手動復位。如果該參數為TRUE,則Event對象需要通過ResetEvent函數手動復位。如果該參數為FALSE,則Event被創建為自動復位的Event,任何等待的線程被恢復執行后,該Event將被系統自動復位。打個比方,如果有10個線程在等待一個Event,這時將Event置位,如果這是個手動復位Event,那么這10個線程將被依次喚醒直到通過ResetEvent調用將該Event復位;如果Event為自動復位Event,那么10個線程中的第一個被喚醒后Event被自動復位,其它線程將繼續等待。
bInitialState參數表明Event對象被創建后默認是否置位。
lpName參數是Event的名字,可以為空表明將創建匿名Event。
CreateEvent函數在調用成功后返回Event句柄。如果同名Event已經存在,則返回這個已經存在了的Event的句柄,此時調用GetLastError函數將返回 ERROR_ALREADY_EXISTS。
還可以通過OpenEvent打開一個已經創建的非匿名Event
HANDLE WINAPI OpenEvent(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
在創建或打開了Event對象之后,可以使用SetEvent和ResetEvent函數來置位或復位一個Event對象。
BOOL WINAPI SetEvent(
HANDLE hEvent
);
BOOL WINAPI ResetEvent(
HANDLE hEvent
);
要等待一個或多個Event對象置位可以使用wait functions。
簡單示例,一個線程不停讀取用戶輸入并放入message列表,另一個線程模擬將message發送出去,如果沒有消息,則發送線程處于阻塞狀態等待,一旦有消息錄入,輸入線程將event置位,發送線程即被激活并逐個發送消息。
#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秒模擬發送所耗時間
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;
}