使用事件对象

事件对象:也属于内核对象(mutex属于内核对象),包含以下三个成员
   1> 使用计数
   2> 用于指明该事件是一个自动重置的事件还是一个人工重置的是件的bool值
   3> 用于指明该事件处于已通知状态还是未通知状态的bool值

使用CreateEvent函数创建事件对象(用一个HANDLE记录)

使用WaitForSingleObject()/WaitForMultipleObject()函数来等待事件对象变为有信号状态。

使用SetEvent()将事件对象置为有信号状态,使用ResetEvent()将事件对象置为无信号状态

 

注释1:对于人工重置的事件对象,需要手动SetEvent和ResetEvent

注释2:对于自动重置的事件对象,需要手动SetEvent为有信号状态,每次有一个Wait等到它的Thread时,它会自动重置为无信号状态

#include <windows.h>
#include
<stdio.h>

#define THREADCOUNT 4

///事件对象,一个全局写EventObj,4个读EventObj
HANDLE ghGlobalWriteEvent;
HANDLE ghReadEvents[THREADCOUNT];

///线程响应函数
DWORD WINAPI ThreadProc(LPVOID);

void CreateEventsAndThreads(void)
{
HANDLE hThread;
DWORD i, dwThreadID;

///创建人工重置、命名的事件对象,初始状态为有信号
///此事件对象用于给主线程来阻止4个读线程的读操作
ghGlobalWriteEvent = CreateEvent(
NULL,
// default security attributes
TRUE, // manual-reset event
TRUE, // initial state is signaled
TEXT("WriteEvent") // object name
);

if (ghGlobalWriteEvent == NULL)
{
printf(
"CreateEvent failed (%d)\n", GetLastError());
return;
}
///保证应用程序只有一个实例运行:通过创建一个命名的事件对象
else if ( GetLastError() == ERROR_ALREADY_EXISTS )
{
printf(
"Named event already exists.\n");
return;
}

// Create multiple threads and an auto-reset event object
// for each thread. Each thread sets its event object to
// signaled when it is not reading from the shared buffer.

for(i = 0; i < THREADCOUNT; i++)
{
// Create the auto-reset event
///创建自动重置、匿名的事件对象,初始状态为有信号
ghReadEvents[i] = CreateEvent(
NULL,
// no security attributes
FALSE, // auto-reset event
TRUE, // initial state is signaled
NULL); // object not named

if (ghReadEvents[i] == NULL)
{
printf(
"CreateEvent failed (%d)\n", GetLastError());
return;
}

///创建Thread,传入各自对应的EventHandle
hThread = CreateThread(NULL,
0,
ThreadProc,
&ghReadEvents[i], // pass event handle
0,
&dwThreadID);

if (hThread == NULL)
{
printf(
"CreateThread failed (%d)\n", GetLastError());
return;
}
}
}

void WriteToBuffer(VOID)
{
DWORD dwWaitResult, i;

///将ghGlobalWriteEvent重置为无信号状态,用来阻止4个读线程的读操作
if (! ResetEvent(ghGlobalWriteEvent) )
{
printf(
"ResetEvent failed (%d)\n", GetLastError());
return;
}

///等待所有的读线程完成read,即ghReadEvents皆变为有信号状态
dwWaitResult = WaitForMultipleObjects(
THREADCOUNT,
// number of handles in array
ghReadEvents, // array of read-event handles
TRUE, // wait until all are signaled
INFINITE); // indefinite wait,无限等待

switch (dwWaitResult)
{
///所有的read-event对象皆变为有信号状态
case WAIT_OBJECT_0:
// TODO: Write to the shared buffer
printf("Main thread writing to the shared buffer...\n");
break;

// An error occurred
default:
printf(
"Wait error: %d\n", GetLastError());
ExitProcess(
0);
}

///将ghGlobalWriteEvent事件对象重置为有信号状态
if (! SetEvent(ghGlobalWriteEvent) )
{
printf(
"SetEvent failed (%d)\n", GetLastError());
ExitProcess(
0);
}

///将ghReadEvents事件对象皆重置为有信号状态
for(i = 0; i < THREADCOUNT; i++)
if (! SetEvent(ghReadEvents[i]) )
{
printf(
"SetEvent failed (%d)\n", GetLastError());
return;
}
}

void CloseEvents()
{
int i;

for( i=0; i < THREADCOUNT; i++ )
CloseHandle(ghReadEvents[i]);

CloseHandle(ghGlobalWriteEvent);
}

void main()
{
int i;

// TODO: Create the shared buffer

// Create the events and THREADCOUNT threads to read from the buffer

CreateEventsAndThreads();

// Write to the buffer three times, just for test purposes

for(i=0; i < 3; i++)
WriteToBuffer();

// Close the events

CloseEvents();
}

DWORD WINAPI ThreadProc(LPVOID lpParam)
{
DWORD dwWaitResult;
HANDLE hEvents[
2];

hEvents[
0] = *(HANDLE*)lpParam; // thread's read event
hEvents[1] = ghGlobalWriteEvent; // global write event

///等待hEvents[0]和hEvents[1]变为有信号状态,也就是ghReadEvents[i]和ghGlobalWriteEvent
dwWaitResult = WaitForMultipleObjects(
2, // number of handles in array
hEvents, // array of event handles
TRUE, // wait till all are signaled,当所有信号量都变为有信号状态,函数才返回
INFINITE); // indefinite wait,无限等待

switch (dwWaitResult)
{
// 所有的EventHandle都变为有信号状态
case WAIT_OBJECT_0:
// TODO: Read from the shared buffer
printf("Thread %d reading from buffer...\n",
GetCurrentThreadId());
break;

// An error occurred
default:
printf(
"Wait error: %d\n", GetLastError());
ExitThread(
0);
}

//重置ghReadEvents[i]为有信号状态,见注释2
if (! SetEvent(hEvents[0]) )
{
printf(
"SetEvent failed (%d)\n", GetLastError());
ExitThread(
0);
}

return 1;
}

原文地址:https://www.cnblogs.com/sifenkesi/p/1983837.html