Внедрение класса сейсмических данных
Правильно ли будет реализован достаточно простой класс безопасного ведения журнала?
Я знаю, что я никогда явно не закрываю TextWriter
, это будет проблема?
Когда я изначально использовал метод TextWriter.Synchronized
, он, похоже, не работал до тех пор, пока я не инициализировал его в статическом конструкторе и не сделал бы его readonly следующим образом:
public static class Logger
{
static readonly TextWriter tw;
static Logger()
{
tw = TextWriter.Synchronized(File.AppendText(SPath() + "\\Log.txt"));
}
public static string SPath()
{
return ConfigManager.GetAppSetting("logPath");
}
public static void Write(string logMessage)
{
try
{
Log(logMessage, tw);
}
catch (IOException e)
{
tw.Close();
}
}
public static void Log(string logMessage, TextWriter w)
{
w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
w.WriteLine(" :");
w.WriteLine(" :{0}", logMessage);
w.WriteLine("-------------------------------");
// Update the underlying file.
w.Flush();
}
}
Ответы
Ответ 1
Я собираюсь использовать совершенно другой подход, чем другие ответы, и предполагаю, что вы действительно хотите узнать, как писать лучший код с поддержкой потоков, и не ищите сторонних предложений от нас (хотя вы можете на самом деле в конечном итоге используйте один.)
Как говорили другие, вы создаете безопасный поток TextWriter
, который означает, что вызовы WriteLine являются потокобезопасными, что не означает, что куча вызовов WriteLine
будет выполняться как атомная операция, Под этим я подразумеваю, что нет гарантии, что четыре вызова WriteLine будут происходить последовательно. У вас может быть поточно-безопасный TextWriter
, но у вас нет потокобезопасного метода Logger.Log
;) Почему? Поскольку в любой момент во время этих четырех вызовов другой поток может также принять вызов Log
. Это означает, что ваши вызовы WriteLine
будут не синхронизированы. Способ исправить это можно с помощью инструкции lock
:
private static readonly object _syncObject = new object();
public static void Log(string logMessage, TextWriter w) {
// only one thread can own this lock, so other threads
// entering this method will wait here until lock is
// available.
lock(_syncObject) {
w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
w.WriteLine(" :");
w.WriteLine(" :{0}", logMessage);
w.WriteLine("-------------------------------");
// Update the underlying file.
w.Flush();
}
}
Итак, теперь у вас есть потокобезопасный TextWriter
И потокобезопасный Logger
.
Имеют смысл?
Ответ 2
При вызове TextWriter.Synchronized будет защищен этот единственный экземпляр TextWriter
, он не будет синхронизировать ваши записи, чтобы один вызов "Журнал" оставался вместе внутри файл.
Если вы вызываете Write
(или Log
с использованием внутреннего экземпляра TextWriter
) из нескольких потоков, индивидуальные вызовы WriteLine
могут быть переплетены, что делает ваши метки даты и времени непригодными для использования.
Я бы лично использовал третье приложение для ведения журнала, которое уже существует для этого. Если это не вариант, синхронизация этого сама (даже с простой блокировкой), скорее всего, будет более полезна, чем использование оболочки TextWriter.Synchronized
.
Ответ 3
Вы должны изучить этот класс (часть .NET 2.0), не нужно "создавать" свой собственный журнал. позволяет вам выполнять вход в текстовый файл, просмотр событий и т.д.
http://msdn.microsoft.com/en-us/library/system.diagnostics.tracesource.aspx
Ваш метод "Log" может выглядеть примерно так (при условии, что существует промежуточная переменная-член, называемая "traceSource" ):
public void Log(TraceEventType eventType, string message)
{
this.traceSource.TraceEvent(eventType, 0, message);
this.traceSource.Flush();
}
Поддержка этого раздела конфигурации, который называет TraceSource и имеет некоторые настройки Config. Предполагается, что когда вы создаете TraceSource в своем журнале, вы создаете его с помощью одного из источников трассировки, названного в config.
<system.diagnostics>
<sources>
<source name="Sample" switchValue="Information,ActivityTracing">
<listeners>
<add name="file"
initializeData="C:\temp\Sample-trace.log"
traceOutputOptions="DateTime"
type="System.Diagnostics.TextWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</listeners>
</source>
</sources>
Кроме того, не делайте свой статичный журнал. Вместо этого используйте Enterprise Library 5.0 Unity для Injection Dependency/IOC.
Надеюсь, это поможет!
Ответ 4
Кто-то указал мне на этот пост, обсуждая сегодня некоторые проблемы с регистрацией. У нас уже есть довольно хорошие ответы, но я добавляю свой ответ, чтобы показать более простую версию класса Logger
, которая делает то же самое, полностью Threadsafe
.
Одно из основных замечаний в этом вопросе заключается в том, что для безопасности потоков не требуется TextWriter.Synchronized
, так как мы пишем файл в правильном lock
.
Примечание. Это уже обсуждалось в разделе комментариев ответа x0n.
public static class Logger
{
static readonly object _locker = new object();
public static void Log(string logMessage)
{
try
{
var logFilePath = Path.Combine(@"C:\YourLogDirectoryHere", "Log.txt");
//Use this for daily log files : "Log" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
WriteToLog(logMessage, logFilePath);
}
catch (Exception e)
{
//log log-exception somewhere else if required!
}
}
static void WriteToLog(string logMessage, string logFilePath)
{
lock (_locker)
{
File.AppendAllText(logFilePath,
string.Format("Logged on: {1} at: {2}{0}Message: {3}{0}--------------------{0}",
Environment.NewLine, DateTime.Now.ToLongDateString(),
DateTime.Now.ToLongTimeString(), logMessage));
}
}
}
Чтобы записать что-то, просто назовите
Logger.Log("Some important event has occurred!");
И он сделает запись в журнале, подобную этой
Записан: 07 октября 2015 в: 02:11:23
Сообщение: Произошло какое-то важное событие!
--------------------
Ответ 5
Если вы ищете простой способ настройки кода, средство уже существует в .NET:
http://msdn.microsoft.com/en-us/library/system.diagnostics.trace.aspx
Кроме того, сторонние инструменты предоставят вам надежные решения для ведения журнала; примеры включают log4net, nLog, и корпоративная библиотека.
Я действительно рекомендую не изобретать колесо на этом:)