My application needs to review all new application Event Log entries as they come in.
private void eventLog_Application_EntryWritten(object sender, EntryWrittenEventArgs e)
{
// Process e.Entry
}
What I would like to know is what happens if another Entry is written to the EventLog while a previous Entry is being handled?
The documentation for EventLog.EntryWritten Event provides an example of handling an entry written event which uses threading (which is why I am asking the question).
In this example they use System.Threading
and call the WaitOne()
and Set()
methods on the AutoResetEvent
class, however I'm not sure precisely what this code is intended to achieve.
The documentation states that - WaitOne()
"blocks the current thread until the current WaitHandle
receives a signal", and that Set()
"sets the state of the event to signaled, allowing one or more waiting threads to proceed". I'm not sure what the threading portion of this example is intended to demonstrate, and how this relates to how (or if) it needs to be applied in practice.
It appears that WaitOne()
blocks the thread immediately after the entry has been written, until it has been handled, where it is then set to signalled (using Set()
), before allowing the thread to proceed. Is this the one and only thread for the application?
Most importantly, when my application is not responsible for writing the the events which need to be read from the EventLog, how should this principle be applied? (If, indeed, it needs to be applied.)
What does happen if a new Entry
is written while the application is inside the handler?
To save event logs right-click the appropriate log file (Application, Security, System, Directory Service, or File Replication Service) then click Save All Events As. Type a name for the file, and click Save.
Open "Event Viewer" by clicking the "Start" button. Click "Control Panel" > "System and Security" > "Administrative Tools", and then double-click "Event Viewer" Click to expand "Windows Logs" in the left pane, and then select "Application". Click the "Action" menu and select "Save All Events As".
Windows event log is an in-depth record of events related to the system, security, and application stored on a Windows operating system. Event logs can be used to track system and some application issues and forecast future problems.
The Write-EventLog cmdlet writes an event to an event log. To write an event to an event log, the event log must exist on the computer and the source must be registered for the event log. The cmdlets that contain the EventLog noun (the EventLog cmdlets) work only on classic event logs.
Nothing dramatic happens, it is serialized by the framework. The underlying winapi function that triggers the EventWritten event is NotifyChangeEventLog(). The .NET Framework uses the threadpool to watch for the event to get signaled with ThreadPool.RegisterWaitForSingleObject(). You can see it being used here.
Which is your cue to why the MSDN sample uses ARE (AutoResetEvent). The event handler runs on that threadpool thread, exactly when that happens is unpredictable. The sample uses a console mode app, without that ARE it would immediately terminate. With the ARE, it displays one notification and quits. Not actually that useful of course, I would personally just have used Console.ReadLine() in the sample so it just keeps running and continues to display info until you press the Enter key.
You don't need this if you use a service or a GUI app, something that's going to run for a long time until the user explicitly closes it. Note the EventLog.SynchronizingObject property, makes it easy to not have to deal with the threadpool thread in a Winforms app.
The example is not really helping to explain the way the AutoResetEvent works in a multi-threaded scenario, so I'll try to explain how I understand it to work.
The AutoResetEvent signal
static variable, is instantiated as a new AutoResetEvent with its signaled state set to false, or "non-signaled", meaning that calling signal.WaitOne()
will cause the thread that called WaitOne
to wait at that point, until the signal
variable is "set" by calling the signal.Set()
method.
I found an explanation of AutoResetEvent that describes it very well in understandable real-world terms, which also included this excellent example below. http://www.albahari.com/threading/part2.aspx#_AutoResetEvent
An AutoResetEvent is like a ticket turnstile: inserting a ticket lets exactly one person through. The “auto” in the class’s name refers to the fact that an open turnstile automatically closes or “resets” after someone steps through. A thread waits, or blocks, at the turnstile by calling WaitOne (wait at this “one” turnstile until it opens), and a ticket is inserted by calling the Set method. If a number of threads call WaitOne, a queue builds up behind the turnstile. (As with locks, the fairness of the queue can sometimes be violated due to nuances in the operating system). A ticket can come from any thread; in other words, any (unblocked) thread with access to the AutoResetEvent object can call Set on it to release one blocked thread.
class BasicWaitHandle
{
static EventWaitHandle _waitHandle = new AutoResetEvent (false);
static void Main()
{
new Thread (Waiter).Start();
Thread.Sleep (1000); // Pause for a second...
_waitHandle.Set(); // Wake up the Waiter.
}
static void Waiter()
{
Console.WriteLine ("Waiting...");
_waitHandle.WaitOne(); // Wait for notification
Console.WriteLine ("Notified");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With