Using Event Objects Program Example
Applications can use event objects in a number of situations to notify a waiting thread of the occurrence of an event. For example, overlapped I/O operations on files, named pipes, and communications devices use an event object to signal their completion. The following example uses event objects to prevent several threads from reading from a shared memory buffer while a master thread is writing to that buffer. First, the master thread uses the CreateEvent() function to create a manual-reset event object whose initial state is nonsignaled. Then it creates several reader threads. The master thread performs a write operation and then sets the event object to the signaled state when it has finished writing. Before starting a read operation, each reader thread uses WaitForSingleObject() to wait for the manual-reset event object to be signaled. When WaitForSingleObject() returns, this indicates that the main thread is ready for it to begin its read operation.
Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.
Then, add the source file and give it a suitable name.
Next, add the following source code.
#define THREADCOUNT 4
DWORD WINAPI ThreadProc(LPVOID);
// Create a manual-reset event object. The write thread sets this
// object to the nonsignaled state when it finishes writing to a shared buffer.
ghWriteEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // initial state is nonsignaled
L"MyWriteEventGedik" // object name
if (ghWriteEvent == NULL)
wprintf(L"CreateEvent() failed, error %d\n", GetLastError());
wprintf(L"CreateEvent() is OK...\n");
// Create multiple threads to read from the buffer.
for(i = 0; i < THREADCOUNT; i++)
// TODO: More complex scenarios may require use of a parameter
// to the thread procedure, such as an event per thread to
// be used for synchronization.
ghThreads[i] = CreateThread(
NULL, // default security
0, // default stack size
ThreadProc, // name of the thread function
NULL, // no thread parameters
0, // default startup flags
if (ghThreads[i] == NULL)
wprintf(L"CreateThread() failed, error %d\n", GetLastError());
wprintf(L"CreateThread() for thread #%d is OK!\n", i);
// TODO: Write to the shared buffer.
wprintf(L"Main thread writing to the shared buffer...\n");
// Set ghWriteEvent to signaled
if (! SetEvent(ghWriteEvent) )
wprintf(L"\nSetEvent() failed, error %d\n", GetLastError());
wprintf(L"\nSetEvent() is OK!\n");
// Close all event handles (currently, only one global handle).
if(CloseHandle(ghWriteEvent) != 0)
wprintf(L"Closing the ghWriteEvent's handle is OK\n");
wprintf(L"Fail to close ghWriteEvent's handle, error %d\n", GetLastError());
wprintf(L"The main() process started...\n");
wprintf(L" With thread #%d\n", GetCurrentThreadId());
// TODO: Create the shared buffer
// Create events and THREADCOUNT threads to read from the buffer
// At this point, the reader threads have started and are most
// likely waiting for the global event to be signaled. However,
// it is safe to write to the buffer because the event is a
// manual-reset event.
wprintf(L"The main thread waiting for threads to exit...\n");
// The handle for each thread is signaled when the thread is terminated.
dwWaitResult = WaitForMultipleObjects(
THREADCOUNT, // number of handles in array
ghThreads, // array of thread handles
TRUE, // wait until all are signaled
// All thread objects were signaled
wprintf(L"All threads ended, cleaning up for application exit...\n");
// An error occurred
wprintf(L"WaitForMultipleObjects failed (%d)\n", GetLastError());
// Close the events to clean up
DWORD WINAPI ThreadProc(LPVOID lpParam)
wprintf(L"Thread %d waiting for the write event...\n", GetCurrentThreadId());
dwWaitResult = WaitForSingleObject(
ghWriteEvent, // event handle
INFINITE); // indefinite wait
// Event object was signaled
// TODO: Read from the shared buffer
wprintf(L"Thread %d reading from buffer...\n", GetCurrentThreadId());
// An error occurred
wprintf(L"WaitForSingleObject() error %d\n", GetLastError());
// Now that we are done reading the buffer, we could use another
// event to signal that this thread is no longer reading. This
// example simply uses the thread handle for synchronization (the
// handle is signaled when the thread terminates.)
wprintf(L"Thread %d exiting...\n", GetCurrentThreadId());
Build and run the project. The following screenshot is a sample output.