事件对象:也属于内核对象(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 ;
}
#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 ;
}