Static Logger в отдельном потоке? - PullRequest
1 голос
/ 02 июня 2010

Я сделал мой Logger, который записывает строку, статический класс со статическим так что я могу назвать это из всего моего проекта без необходимости делать его экземпляр. довольно хорошо, но я хочу, чтобы он работал в отдельном потоке, так как доступ к файлу стоит времени

возможно ли это как-то и как это лучше всего сделать?

Это краткое описание, но я надеюсь, что идея ясна. если нет, пожалуйста, дайте мне знать.

Заранее спасибо!

Кстати, любые другие улучшения в моем коде приветствуются, у меня такое ощущение, что не все так эффективно, как может быть:

internal static class MainLogger
    {
        internal static void LogStringToFile(string logText)
        {
            DateTime timestamp = DateTime.Now;
            string str = timestamp.ToString("dd-MM-yy  HH:mm:ss ", CultureInfo.InvariantCulture) + "\t" + logText + "\n";
            const string filename = Constants.LOG_FILENAME;
            FileInfo fileInfo = new FileInfo(filename);
            if (fileInfo.Exists)
            {
                if (fileInfo.Length > Constants.LOG_FILESIZE)
                {
                    File.Create(filename).Dispose();
                }
            }
            else
            {
                File.Create(filename).Dispose();
            }
            int i = 0;
            while(true)
            {
                try
                {
                    using (StreamWriter writer = File.AppendText(filename))
                    {
                        writer.WriteLine(str);
                    }
                    break;
                }
                catch (IOException)
                {
                    Thread.Sleep(10);
                    i++;
                    if (i >= 8)
                    {
                        throw new IOException("Log file \"" + Constants.LOG_FILENAME + "\" not accessible after 5 tries");
                    }
                }
            }
        }
    }
enter code here

Ответы [ 5 ]

3 голосов
/ 02 июня 2010

Если вы делаете это как упражнение (просто использовать готовый регистратор не вариант), вы можете попробовать систему производитель / потребитель.

  1. Либо создайте функцию Init для своего регистратора, либо используйте статический конструктор - внутри него запустите новый System.Threading.Thread, который просто проходит через цикл while(true).
  2. Создайте новый Queue<string> и включите в него функцию регистрации.
  3. Ваш цикл while(true) ищет элементы в очереди, удаляет их из очереди и регистрирует их.
  4. Убедитесь, что вы заблокировали свою очередь, прежде чем делать что-либо с ней в любом потоке.
3 голосов
/ 02 июня 2010

извините, но вы не можете изобретать велосипед:
выберите log4net (или любой другой (корпоративный) механизм регистрации) в качестве регистратора!

1 голос
/ 02 июня 2010

Хорошо, проще говоря, вам нужно создать статический класс ThreadSafe. Ниже приведены некоторые фрагменты кода, делегат, который вы вызываете из любого потока, это указывает на правильный поток, который затем вызывает функцию WriteToFile.

Когда вы запускаете приложение, в которое хотите войти, передайте ему следующее, где LogFile - это имя файла и путь к вашему файлу журнала.

Log.OnNewLogEntry += Log.WriteToFile (LogFile, Program.AppName);

Тогда вы хотите поместить это в ваш статический класс Logging. Бит мастера - это функция ThreadSafeAddEntry, которая гарантирует, что вы находитесь в правильном потоке для записи строки кода.

public delegate void AddEntryDelegate(string entry, bool error);

public static Form mainwin;

public static event AddEntryDelegate OnNewLogEntry;

public static void AddEntry(string entry) {
  ThreadSafeAddEntry( entry, false );
}

private static void ThreadSafeAddEntry (string entry, bool error)
    {
    try
        {
        if (mainwin != null && mainwin.InvokeRequired)  // we are in a different thread to the main window
            mainwin.Invoke (new AddEntryDelegate (ThreadSafeAddEntry), new object [] { entry, error });  // call self from main thread
        else
            OnNewLogEntry (entry, error);
        }
    catch { }
    }

public static AddEntryDelegate WriteToFile(string filename, string appName) {
    //Do your WriteToFile work here
    }
}

И, наконец, написать строку ...

Log.AddEntry ("Hello World!");
0 голосов
/ 02 июня 2010

Для начала, ваш механизм регистрации должен, как правило, избегать создания исключений. Зачастую в механизмы журналирования записываются ошибки, поэтому все становится ужасно, когда они также начинают ошибаться.

Я бы заглянул в класс BackgroundWorker , так как он позволяет вам раскручивать потоки, которые могут выполнять регистрацию за вас. Таким образом, ваше приложение не замедляется, а возникающие исключения просто игнорируются.

0 голосов
/ 02 июня 2010

В этом случае у вас есть типичный сценарий для потребителя-производителя: многие потоки создают записи журнала, а один поток записывает их в файл. В MSDN есть статья с примером кода для этого сценария .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...