我使用C#和.Net的EventLog
类写了一些写入Windows事件日志的代码,这是一个间歇性的问题。
基本上,这段代码完全可以日常工作,但偶尔也会出现这样的错误:
“System.ArgumentException:只有 自定义日志的前八个字符 名字很重要,而且有 已经有另一个系统登录了 使用前八个字符 给出的名字。姓名: 'Application',现有日志的名称: '应用程序'。“
我可以从我们日志中的其他信息中识别出受影响的调用堆栈是这样的 - 您可以清楚地看到我实际上正在尝试写入现有的LB_Email
日志(LogEmail
被调用第一):
public static void LogEmail(string to, string type)
{
string message = String.Format("{0}\t{1}\t{2}", DateTime.Now, to, type);
Log(message, "LB_Email", EventLogEntryType.Information);
}
private static void Log(string message, string logName, EventLogEntryType type)
{
using (EventLog aLog = new EventLog())
{
aLog.Source = logName;
aLog.WriteEntry(message, type);
}
}
一旦错误开始发生,似乎对我们的LB_Email
事件日志的访问以某种方式被锁定 - 在特定事件日志上查看属性显示大多数信息灰显且不可更改,并且其他进程似乎被阻止记录到那个日志也是。但是,我看到错误(使用上面相同的Log方法)通过try-catch记录到'LB_Error'日志,并继续按预期运行。
我从多线程应用程序调用此代码,但我无法确定上面的代码是否是线程安全的。
我还可以确认在杀死并重新启动进程后,有问题的日志再次正常运行...并且它有适当的设置以在条目满了时重用条目...虽然我不认为这是问题
我很想听听你的意见和建议。
答案 0 :(得分:4)
您只能使用Source来编写 一次一个日志
所以我怀疑这个问题是由你的多线程应用程序在给定时间和同一个源上调用Log
方法一次更多引起的。
我建议您使用线程安全的单例类来记录这些事件,而不是静态类(或方法)。
编辑:
Jon Skeet对单身人士有excellent article。
如果您不想实现单例类,可以执行以下操作:
static readonly object lockObj = new object();
public static void LogEmail(string to, string type)
{
string message = String.Format("{0}\t{1}\t{2}", DateTime.Now, to, type);
Log(message, "LB_Email", EventLogEntryType.Information);
}
private static void Log(string message, string logName, EventLogEntryType type)
{
lock (lockObj)
{
using (EventLog aLog = new EventLog())
{
aLog.Source = logName;
aLog.WriteEntry(message, type);
}
}
}
希望这能解决你的问题。
答案 1 :(得分:0)
谢谢布鲁诺,
那么,我错误地认为Log方法中的EventLog实例与另一个线程中同一方法调用中的EventLog实例不同?或者我只是对静态方法中的对象实例感到困惑?
好的,所以我有几个Log(...)方法的包装器方法。如果我将Log方法移动到单例类中,更改了包装器(LogEmail,LogXxxx,LogYyy等),那么我可以保持我的Log.Zzzz接口相同,但利用单例LogSingleton.Instance.Log(...)的安全性来自当前的日志。或者因为我想写入不同的日志,每个日志都需要自己的LogSingletonXxx吗?
你可以说我很困惑:)是的 - 我真的很感激一些同步代码:)
NIJ