我的应用程序需要在进入时查看所有新的应用程序事件日志条目。
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
会发生什么?
答案 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就像票证旋转门票:插入票证让 一个人通过。类名中的“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属性,并且另一个线程可以在更改该属性后写入消息。