In all kernel objects, the event kernel object is the most basic object. Event to notify that an operation has been completed.
Client and a server that need to communicate with each other example (VS2008)
The composition of the event kernel object
A usage count (as with all kernel objects),
A Boolean value that indicates whether the event is an auto-reset event or an event that is manually reset.
A Boolean value that indicates whether the event is in a notified or non-notification state.
There are two different kinds of event objects
One is a manually reset event, and the other is an automatically reset event.
When a manually reset event is notified , all lines waiting for the event are threads into a scheduler thread.
when an automatically reset event is notified, only one thread in the thread that waits for the event becomes a scheduled thread.
Events are used most when one thread performs an initialization operation and then notifies another thread to perform the remaining operations. The event is initialized to an unspecified state, and then, when the thread finishes its initialization, it sets the event to the notified state. At this point, the other thread that has been waiting for the event discovers that the event has been notified, so it becomes a scheduled thread. This second thread knows that the first thread has completed its operation.
with CreateEvent function Creation Event Kernel object
HANDLE CreateEvent (
Psecurity_attributes PSA,
BOOL Fmanualreset,
BOOL Finitialstate,
Pctstr Pszname
);
The operating techniques for kernel objects are described in the previous sections, such as how to set their security, how to use counts, how to inherit their handles, how to share objects by name, and so on.
The Fmannualreset parameter is a Boolean value that tells the system whether to create a manually reset event (TRUE) or to create an auto-reset event (FALSE).
The Finitialstate parameter is used to indicate whether the event is to be initialized to the notified state (TRUE) or to an unspecified state (FALSE). When the system creates an event object, CreateEvent returns the process-related handle to the event object.
Threads in other processes can gain access to the object by using the same values passed in the Pszname parameter (see: Named objects), using inheritance, using DuplicateHandle functions to invoke CreateEvent, or calling OpenEvent, In the Pszname parameter, set a name that matches the name set when you call CreateEvent:
HANDLE OpenEvent (
DWORD fdwaccess,
BOOL Finherit,
Pctstr Pszname
);
As in all cases, the CloseHandle function should be called when an event kernel object is no longer needed.
Once the event has been created, you can directly control its state
When you call SetEvent, you can change the event to a notification state:
BOOL SetEvent(HANDLE hevent);
When you call the ResetEvent function, you can change the event to a non-notification state:
BOOL resetevent(HANDLE hevent);
Side effects of event success waiting
Auto-Reset Events: automatically resets to the non-notification state (so it is usually not necessary to call the ResetEvent function for an automatically reset event). That's why his name is automatically two words.
Manually reset events: Microsoft did not define the side effects of a successful wait for an event that was manually reset. So it's called Labor.
A simple example of how to use the event kernel object to synchronize threads
This example clearly shows the difference between using a manual reset event and an auto-reset event.
Create a global handle to a Manual-reset, nonsignaled event.
HANDLE g_hevent;
int WINAPI WinMain (...)
{
Create the Manual-reset, nonsignaled event.
G_hevent = CreateEvent (null, TRUE, FALSE, NULL); Artificial
Spawn 3 new threads.
HANDLE Hthread[3];
DWORD dwThreadID;
Hthread[0] = _beginthreadex (null, 0, WordCount, NULL, 0, &dwthreadid);
HTHREAD[1] = _beginthreadex (null, 0, spellcheck, NULL, 0, &dwthreadid);
HTHREAD[2] = _beginthreadex (null, 0, grammarcheck, NULL, 0, &dwthreadid);
Openfileandreadcontentsintomemory (...);
Allow any 3 threads to access the memory.
SetEvent (g_hevent); Set the event notification status
...
}
DWORD WINAPI WordCount (PVOID pvparam)
{
Wait until the file ' s data is in memory.
WaitForSingleObject (G_hevent, INFINITE);
Access the memory block.
...
return (0);
}
DWORD WINAPI spellcheck (PVOID pvparam)
{
Wait until the file ' s data is in memory.
WaitForSingleObject (G_hevent, INFINITE);
Access the memory block.
...
return (0);
}
DWORD WINAPI Grammarcheck (PVOID pvparam)
{
Wait until the file ' s data is in memory.
WaitForSingleObject (G_hevent, INFINITE);
Access the memory block.
...
return (0);
}
When this process starts, it creates an event that is manually reset to the non-notification state, and the handle is saved in a global variable. This makes it very easy for other threads in the process to access the same event object. Now 3 threads have been generated. These threads wait for the contents of the file to be read into memory, and then each thread accesses its data. One thread makes a word count, another thread runs the spelling checker, and the third thread runs the grammar checker. The beginning of the code for these 3 thread functions is the same, with each function calling WaitForSingleObject, which causes the thread to pause until the contents of the file are read into memory by the main thread.
Once the main thread has the data ready, it calls SetEvent, giving the event a notification signal. At this point, the system causes all 3 worker threads to enter a scheduled state, both of which have CPU time and access to memory blocks. Note that all 3 threads access memory in read-only mode. This is the only reason that all 3 threads can run at the same time. Also note that if you have more than one CPU on your computer, all 3 threads can actually run concurrently, allowing you to do a lot of work in a very short period of time.
If you use an auto-reset event instead of an event that is manually reset, there is a big difference in the behavior characteristics of the application. When the main thread calls SetEvent, the system only allows one worker thread to become a scheduled state. Similarly, there is no guarantee that the system will make which thread becomes a scheduled state. The remaining two worker threads will continue to wait.
A thread that has become a scheduled state has exclusive access to a block of memory. Let's rewrite the thread's functions so that each function calls the SetEvent function before returning (just as the WinMain function does). These thread functions now become the following form:
DWORD WINAPI WordCount (PVOID pvparam)
{
Wait until the file ' s data is in memory.
WaitForSingleObject (G_hevent, INFINITE);
Access the memory block.
...
SetEvent (g_hevent);
return (0);
}
DWORD WINAPI spellcheck (PVOID pvparam)
{
Wait until the file ' s data is in memory.
WaitForSingleObject (G_hevent, INFINITE);
Access the memory block.
...
SetEvent (g_hevent);
return (0);
}
DWORD WINAPI Grammarcheck (PVOID pvparam)
{
Wait until the file ' s data is in memory.
WaitForSingleObject (G_hevent, INFINITE);
Access the memory block.
...
SetEvent (g_hevent);
return (0);
}
When a thread finishes its specialized delivery of data, it calls the SetEvent function, which allows the system to make one of the two waiting threads a scheduled thread. Again, we do not know which thread the system will select as a scheduler thread, but the thread will do its own dedicated delivery of memory blocks. When the thread finishes the operation, it also calls the SetEvent function so that the third and last thread makes its own pass to the memory block. Note that when an automatic reset event is used, if each worker thread accesses the block of memory in read/write mode, there is no problem, and these threads are no longer required to treat the data as read-only data.
BOOL PulseEvent (HANDLE hevent);
The PulseEvent function makes the event a notified state and then immediately becomes an unnamed state, as if the ResetEvent function were called immediately after calling SetEvent. If you call the PulseEvent function on an event that is manually reset, then any thread or all threads waiting for the event will become a scheduled thread when the event is emitted. If you call the PulseEvent function on an automatic reset event, only one thread that waits for the event becomes a scheduled thread. If no thread waits for the event when the event is emitted, it will not have any effect.
The PulseEvent function is not very useful (you can ignore it first).
Original address: http://www.cnblogs.com/fangyukuan/archive/2010/09/04/1817750.html
(go) Kernel Thread Object--event event object