如果在将应用程序放入上一个条目的处理程序内部时将新条目写入事件日志会发生什么?

时间:2015-04-16 13:57:16

标签: c# .net thread-safety event-log

我的应用程序需要在进入时查看所有新的应用程序事件日志条目。

private void eventLog_Application_EntryWritten(object sender, EntryWrittenEventArgs e)
{
    // Process e.Entry    
}

我想知道的是,如果在处理前一个条目时将另一个条目写入EventLog会发生什么?


EventLog.EntryWritten Event的文档提供了一个处理使用线程的条目写入事件的示例(这就是我提出问题的原因)。

在此示例中,他们使用System.Threading并调用WaitOne()类上的Set()AutoResetEvent方法,但我不确定此代码是什么打算实现。

文档说明 - WaitOne()"阻止当前线程,直到当前WaitHandle收到信号",Set()"设置状态发出信号的事件,允许一个或多个等待线程继续进行#34;我不确定此示例的线程部分旨在演示什么,以及它与如何(或是否)在实践中应用的关系。

似乎WaitOne()在写入条目后立即阻塞线程,直到它被处理,然后在允许线程继续之前将其设置为发信号(使用Set()) 。这是应用程序的唯一线程吗?

最重要的是,当我的应用程序 负责负责编写需要从EventLog读取的事件时,该原则应该如何应用? (如果确实需要应用它。)

当应用程序在处理程序内部时,如果写入新的Entry会发生什么?

3 个答案:

答案 0 :(得分:5)

没有任何戏剧性的事情发生,它是由框架序列化的。触发EventWritten事件的基础winapi函数是NotifyChangeEventLog()。 .NET Framework使用线程池来监视事件以通过ThreadPool.RegisterWaitForSingleObject()发出信号。你可以看到它是used here

MSDN示例使用ARE(AutoResetEvent)的原因是什么?事件处理程序在该线程池线程上运行,恰好在发生这种情况时是不可预测的。该示例使用控制台模式应用程序,没有它会立即终止。使用ARE,它会显示一个通知并退出。当然不是那么有用,我个人只是在示例中使用了Console.ReadLine(),所以它只是继续运行并继续显示信息,直到你按下Enter键。

如果您使用服务或GUI应用程序,那么您将不需要这样做,这将在用户明确关闭之前运行很长时间。注意EventLog.SynchronizingObject属性,可以轻松地在Winforms应用程序中处理线程池线程。

答案 1 :(得分:1)

该示例并没有真正帮助解释AutoResetEvent在多线程场景中的工作方式,因此我将尝试解释我如何理解它的工作原理。

AutoResetEvent signal静态变量被实例化为新的AutoResetEvent,其信号状态设置为false或“非信号”,这意味着调用signal.WaitOne()将导致调用{{1}的线程等待那一点,直到通过调用WaitOne方法“设置”signal变量。

我找到了一个AutoResetEvent的解释,它在可理解的现实世界术语中很好地描述了它,下面还包括这个优秀的例子。 http://www.albahari.com/threading/part2.aspx#_AutoResetEvent

的AutoResetEvent

  

AutoResetEvent就像票证旋转门票:插入票证让   一个人通过。类名中的“auto”是指   开放式旋转门自动关闭或“重置”之后的事实   有人走过了。一个线程在十字转门处等待或阻塞   调用WaitOne(等待这个“一个”旋转门,直到它打开),然后a   通过调用Set方法插入ticket。如果有多个线程   调用WaitOne,一个队列在十字转门后面建立起来。 (和锁一样,   由于细微差别,有时可能会违反队列的公平性   操作系统)。票可以来自任何线程;其他   单词,任何(未阻止的)线程,可以访问AutoResetEvent对象   可以调用Set on it来释放一个被阻塞的线程。

signal.Set()

答案 2 :(得分:0)

根据https://msdn.microsoft.com/en-us/library/0680sfkd.aspx,事件日志组件不是线程安全的,并且该代码用于防止同时交互中的意外行为。

  

如果多个线程同时执行这些行,则一个线程可以更改事件日志的EventLog.Source属性,并且另一个线程可以在更改该属性后写入消息。