Журналы событий и многопоточные компоненты
Журналы событий предназначены для отслеживания важных событий во время выполнения приложения. В журналы событий записываются данные, которые могут пригодиться при устранении неполадок или анализе производительности. При записи событий для многопоточных компонентов необходимо учитывать дополнительные особенности. Во-первых, должен быть предусмотрен механизм для записи идентификационных данных потока, в котором регистрируется сообщение. Во-вторых, при взаимодействии с журналом событий должны быть приняты во внимание вопросы потокобезопасности. Во избежание состояния гонки поток, пытающийся записать сообщение, должен установить монопольную блокировку для журнала. Обзор журналов событий см. в разделе Администрирование журналов событий. Дополнительные сведения о потокобезопасности см. в разделе Потокобезопасные компоненты.
Чтобы идентифицировать каждый поток, необходимо задать значение свойства Thread.Name. Это свойство принимает и возвращает значение типа String и может быть использовано для назначения уникального идентификатора каждому потоку. Затем это значение можно передать в метод EventLog.CreateEventSource, чтобы определить данный поток в качестве источника событий для других потоков. При записи событий в журнал поток может задать свое имя в качестве значения свойства Source журнала событий, обеспечивая таким образом точность записи событий.
Если несколько строк кода выполняются в многопоточной среде, важно, чтобы перед выполнением любого кода потоки устанавливали монопольные блокировки для журнала событий. Рассмотрим, например, следующие строки кода, выполняющиеся в многопоточной среде:
MyEventLog.Source = Threading.Thread.CurrentThread.Name.ToString
EventLog.WriteEntry("What thread did this come from?", "myApplication")
MyEventLog.Source = System.Threading.Thread.CurrentThread.Name.ToString();
EventLog.WriteEntry("What thread did this come from?", "myApplication");
Если несколько потоков выполняют эти строки кода одновременно, то в одном потоке может быть изменено свойство EventLog.Source журнала событий, а в другом потоке — записано сообщение уже после изменения значения этого свойства. Чтобы избежать подобных ситуаций, можно перед выполнением кода из нескольких потоков установить монопольную блокировку объекта с помощью оператора SyncLock (Visual Basic) или lock (C#). С использованием блокировок предыдущий пример будет выглядеть следующим образом:
SyncLock MyEventLog
MyEventLog.Source = System.Threading.Thread.CurrentThread.Name.ToString
EventLog.WriteEntry("What thread did this come from?", "myApplication")
End SyncLock
lock(MyEventLog)
{
MyEventLog.Source = Threading.Thread.CurrentThread.Name.ToString();
EventLog.WriteEntry("What thread did this come from?",
"myApplication");
}
Для записи событий, которые происходят в многопоточных приложениях, можно также использовать классы Debug и Trace. Эти классы являются статическими и позволяют отправлять выходные данные в окно вывода, окно консоли, текстовый файл, журнал событий или другие объекты. Дополнительные сведения см. в разделе Трассировка и оборудование приложений в Visual Basic и Visual C#.
См. также
Задачи
Практическое руководство. Ведение журнала событий для многопоточных компонентов