Подтвердить что ты не робот

Внедрение класса сейсмических данных

Правильно ли будет реализован достаточно простой класс безопасного ведения журнала?

Я знаю, что я никогда явно не закрываю 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();
    }
}
4b9b3361

Ответ 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, и корпоративная библиотека.

Я действительно рекомендую не изобретать колесо на этом:)