Периодическое исключение журнала событий
-
11-07-2019 - |
Вопрос
У меня периодически возникает проблема с некоторым кодом, который записывает в журнал событий Windows, используя C# и .Net. EventLog
сорт.
По сути, этот код отлично работает изо дня в день, но очень редко мы начинаем получать такие ошибки:
"System.ArgumentException:Только первые восемь символов пользовательского имени журнала являются значительными, и уже есть еще один журнал в системе, использующий первые восемь символов указанного имени.Имя дано:«Приложение», имя существующего журнала:'Приложение'."
По другой информации в наших журналах я могу определить, что затронутый стек вызовов выглядит следующим образом: вы ясно видите, что я на самом деле пытаюсь выполнить запись в существующий стек вызовов. 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
Журнал событий каким-то образом заблокирован - при просмотре свойств конкретного журнала событий большая часть информации отображается серым цветом и неизменяемой, а другим процессам также запрещено регистрироваться в этом журнале.Тем не менее, я вижу ошибку (которая использует тот же метод журнала, описанный выше) через try-catch, который регистрируется в журнале «LB_Error» и продолжает работать так, как ожидалось.
Я вызываю этот код из многопоточного приложения, но мне не удалось определить, является ли приведенный выше код потокобезопасным или нет.
Я также могу подтвердить, что рассматриваемый журнал снова работает нормально после завершения и перезапуска процесса...и у него были соответствующие настройки для повторного использования записей, когда они заполнялись...хотя я не думаю, что это было проблемой.
Я хотел бы услышать ваши мысли и предложения.
Решение
А документация говорится, что:
Вы можете использовать источник только для того, чтобы записать в один журнал за раз
Поэтому я подозреваю, что эта проблема вызвана тем, что ваше многопоточное приложение вызывает Log
метод более одного раза в заданное время и для одного и того же источника.
Я предлагаю вместо статического класса (или методов) использовать поточно-ориентированный одноэлементный класс для регистрации этих событий.
РЕДАКТИРОВАТЬ:
У Джона Скита есть отличная статья на синглтонах.
Если вы не хотите реализовывать одноэлементный класс, вы можете сделать что-то вроде этого:
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);
}
}
}
Надеюсь, это решит вашу проблему.
Другие советы
Спасибо, Бруно,
Итак, ошибаюсь ли я, думая, что экземпляр EventLog в методе Log отличается от экземпляра EventLog в том же вызове метода в другом потоке?Или я просто запутался в экземплярах объектов внутри статического метода?
Хорошо, у меня есть несколько методов-оболочек для метода Log(...).Если бы я переместил метод Log в одноэлементный класс, изменил оболочки (LogEmail, LogXxxx, LogYyy и т. д.), тогда я мог бы сохранить свои интерфейсы Log.Zzzz такими же, но использовать безопасность одноэлементного LogSingleton.Instance.Log(...) из текущих журналов.ИЛИ, поскольку я хочу писать в разные журналы, потребуется ли для каждого из них собственный LogSingletonXxx?
Вы можете сказать, что я в замешательстве :) Да, я был бы очень признателен за код синхронизации :)
Нидж