使用事件对象

【勇芳软件工作室】汉化HomePreviousNext

基于Win32的应用程序在许多情况下使用事件对象来通知等待线程发生事件。例如,对文件,命名管道和通信设备的重叠I / O操作使用事件对象来表示完成。有关在重叠I / O操作中使用事件对象的更多信息,请参阅同步和重叠输入和输出.

在以下示例中,应用程序使用事件对象来防止在主线程正在写入该缓冲区时,多个线程从共享内存缓冲区中读取。首先,主线程使用CreateEvent函数创建手动重置事件对象。主线程在写入缓冲区时将事件对象设置为非信号,然后在完成写入时将对象重置为发信号。然后它为每个线程创建几个读取器线程和自动重置事件对象。每个读取器线程将其事件对象设置为在不从缓冲器读取时发出信号。

#define NUMTHREADS 4

HANDLE hGlobalWriteEvent;

void CreateEventsAndThreads(void)

{

HANDLE hReadEvents[NUMTHREADS], hThread;

DWORD i, IDThread;

//创建手动重置事件对象。主线程集

//这在写入共享缓冲区时被忽略。

hGlobalWriteEvent = CreateEvent(

NULL, //没有安全属性

TRUE, //手动重置事件

TRUE, //初始状态发出信号

"WriteEvent" //对象名称

);

if (hGlobalWriteEvent == NULL) {

//错误退出

}

//创建多个线程和自动重置事件对象

//每个线程每个线程将其事件对象设置为

//当没有从共享缓冲区读取时发出信号。

for(i = 1; i <= NUMTHREADS; i++)

{

//创建自动重置事件。

hReadEvents[i] = CreateEvent(

NULL, //没有安全属性

FALSE, //自动重置事件

TRUE, //初始状态发出信号

NULL); //对象未命名

if (hReadEvents[i] == NULL)

{

//错误退出。

}

hThread = CreateThread(NULL, 0,

(LPTHREAD_START_ROUTINE)ThreadFunction,

&hReadEvents[i], //传递事件句柄

0, &IDThread);

if (hThread == NULL)

{

//错误退出。

}

}

}

在主线程写入共享缓冲区之前,它使用ResetEvent函数将hGlobalWriteEvent(应用程序定义的全局变量)的状态设置为非信号。这将阻止读取器线程启动读操作。然后,主机使用WaitForMultipleObjects函数等待所有读取器线程完成当前的所有读操作。当WaitForMultipleObjects返回时,主线程可以安全地写入缓冲区。完成之后,它将hGlobalWriteEvent和所有读取器线程事件设置为发信号,使读者线程恢复读操作。

VOID WriteToBuffer(VOID)

{

DWORD dwWaitResult, i;

//将hGlobalWriteEvent重置为非指定,阻止读者。

如果(!ResetEvent(hGlobalWriteEvent))

{

//错误退出。

}

//等待所有阅读线程完成阅读。

dwWaitResult = WaitForMultipleObjects(

NUMTHREADS, //数组中的句柄数

hReadEvents, //读取事件句柄数组

TRUE, //等到所有的都发出信号

INFINITE); //无限期等待

switch(dwWaitResult)

{

//所有读事件对象都发出信号。

case WAIT_OBJECT_0:

//写入共享缓冲区。

break;

//发生错误

默认:

printf("Wait error: %d\n", GetLastError());

ExitProcess(0);

}

//将hGlobalWriteEvent设置为发信号。

如果(!SetEvent的(hGlobalWriteEvent))gl

{

//错误退出。

}

//将所有读取的事件设置为发信号。

for(i = 1; i <= NUMTHREADS; i++)

如果(!SetEvent的(989796010个hReadEvents {})){gl

//错误退出。

}

}

在开始读操作??之前,每个阅读器线程使用WaitForMultipleObjects等待应用程序定义的全局变量hGlobalWriteEvent及其自己的读事件。当WaitForMultipleObjects返回时,读取器线程的自动复位事件已被重置为非信号。这将阻止主线程写入缓冲区,直到读取器线程使用SetEvent函数将事件的状态设置为发送信号。

VOID ThreadFunction(LPVOID lpParam)

{

DWORD dwWaitResult, i;

HANDLE hEvents[2];

hEvents[0] = (HANDLE) *lpParam; //线程的读取事件

hEvents[1] = hGlobalWriteEvent;

dwWaitResult = WaitForMultipleObjects(

2, //数组中的句柄数

hEvents, //事件句柄数组

TRUE, //等到所有的信号

INFINITE); //无限期等待

switch(dwWaitResult)

{

//两个事件对象都发出信号。

case WAIT_OBJECT_0:

//从共享缓冲区读取。

break;

//发生错误

默认:

printf("Wait error: %d\n", GetLastError());

ExitThread(0);

}

//将读取的事件设置为发信号。

如果(!SetEvent的(989796014个Hevents {}))gl

{

//错误退出。

}

}