创建 Event 的 Windows API 函数签名是:
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName
);
参数和返回值的说明如下:
一个无信号的 Event 对象,我们可以通过 SetEvent 将其变成受信状态,SetEvent 的函数签名如下:BOOL SetEvent(HANDLE hEvent); 参数 hEvent 设置为需要设置信号的 Event 句柄即可。
同理,一个已经受信的 Event 对象,可以使用 ResetEvent 对象将其变成无信号状态,ResetEvent 的函数签名如下:BOOL ResetEvent(HANDLE hEvent); 参数 hEvent 即我们需要重置的 Event 对象句柄。
例子,假设现在有两个线程,其中一个是主线程,主线程等待工作线程执行某一项耗时的任务完成后,将任务结果显示出来。代码如下:
#include <Windows.h>
#include <string>
#include <iostream>
bool g_bTaskCompleted = false;
std::string g_TaskResult;
HANDLE g_hTaskEvent = NULL;
DWORD __stdcall WorkerThreadProc(LPVOID lpThreadParameter)
{
//使用 Sleep 函数模拟一个很耗时的操作
//睡眠3秒
Sleep(3000);
g_TaskResult = "task completed";
g_bTaskCompleted = true;
//设置事件信号
SetEvent(g_hTaskEvent);
return 0;
}
int main()
{
//创建一个匿名的手动重置初始无信号的事件对象
g_hTaskEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE hWorkerThread = CreateThread(NULL, 0, WorkerThreadProc, NULL, 0, NULL);
DWORD dwResult = WaitForSingleObject(g_hTaskEvent, INFINITE);
if (dwResult == WAIT_OBJECT_0)
{
std::cout << g_TaskResult << std::endl;
}
CloseHandle(hWorkerThread);
CloseHandle(g_hTaskEvent);
return 0;
}
Event 对象有两个显著的特点:
WaitForSingleObject 等待该 Event 对象受信,而是在这之后才调用 WaitForSingleObject ,仍然能检测到事件的受信状态,即不会丢失信号,而后面要介绍的条件变量就可能会丢失信号。