What happens if a new Entry is written to the Event Log while the application is inside the handler for a previous entry being written?
Asked Answered
E

3

7

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?

Embraceor answered 16/4, 2015 at 13:57 Comment(2)
Have you heard of locks? Essentially, you "lock" the object to be in your control, and when it's done, it "unlocks" the object. When another thread wants control, it waits until no other thread has a lock on it. In pseudocode form (obj is the variable we want to use): object lock; while (obj.IsLocked) { /* wait by doing nothing */ } if ((lock = obj.Lock()) == null) { /* failed */ } else { /* log */ obj.Unlock(lock); }Disciple
I have, thank you. I'm just struggling to wrap my head around the specifics of the example and what it's trying to do (and, more importantly, what I need to do to properly handle the entries being written to the EventLog)Embraceor
C
7

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.

Chilli answered 20/4, 2015 at 14:39 Comment(2)
So, I don't need to use threading and my GUI application will still pick up every event?Embraceor
The .NET Framework takes care of it, you don't have to help. Just don't forget that the event is raised on a threadpool thread, you cannot directly update your UI. Unless you use the SynchronizingObject property.Chilli
R
1

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

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");
  }
}
Remarque answered 20/4, 2015 at 14:11 Comment(0)
A
0

According to https://msdn.microsoft.com/en-us/library/0680sfkd.aspx the eventlog components are not thread-safe and that code is there to prevent unexpected behaviour in simultaneous interactions.

If multiple threads are executing these lines simultaneously, if is possible for one thread to change the EventLog.Source Property of the event log, and for another thread to write a message, after that property had been changed.

Ancona answered 20/4, 2015 at 14:5 Comment(1)
Is this applicable to reading from the EventLog in the same way? The example only seems to discuss writing to the EventLog.Embraceor

© 2022 - 2024 — McMap. All rights reserved.