BackgroundWorker & Timer, чтение только новых строк файла журнала? - PullRequest
10 голосов
/ 01 декабря 2010

Мое приложение записывает файл журнала (в настоящее время используется log4net ).Я хотел бы настроить таймер и фоновый рабочий для чтения файла журнала и печати его содержимого в некоторый элемент управления в моей форме, пока он записывается.

Я не могу использовать FileSystemWatcher класс, потому что кажется сломанным: иногда событие «менялось», иногда нет.И у него чрезвычайно низкая «скорость объединения».

Поэтому я создал Timer и FileSystemWatcher.В случае «отметки» таймера фоновый работник выполняет свою работу.

Вопрос: как читать только те строки, которые были добавлены с момента последней проверки работника?

public LogForm()
{
    InitializeComponent();
    logWatcherTimer.Start();
}

private void logWatcherTimer_Tick(object sender, EventArgs e)
{
    FileInfo log = new FileInfo(@"C:\log.txt");
    if(!logWorker.IsBusy) logWorker.RunWorkerAsync(log);
}

private void logWorker_DoWork(object sender, DoWorkEventArgs e)
{
    // Read only new lines since last check.
    FileInfo log = (FileInfo) e.Argument;

   // Here is the main question!
}

РЕДАКТИРОВАТЬ: Решение кода (может быть, есть более элегантный способ?):

private void logWatherWorker_DoWork(object sender, DoWorkEventArgs e)
{
    // retval
    string newLines = string.Empty;
    FileInfo log = (FileInfo) e.Argument;

    // Just skip if log file hasn't changed
    if (lastLogLength == log.Length) return;

    using (StreamReader stream = new StreamReader(log.FullName))
    {
        // Set the position to the last log size and read
        // all the content added
        stream.BaseStream.Position = lastLogLength;
        newLines = stream.ReadToEnd();
    }

    // Keep track of the previuos log length
    lastLogLength = log.Length;

    // Assign the result back to the worker, to be
    // consumed by the form
    e.Result = newLines;
}

Ответы [ 3 ]

3 голосов
/ 01 декабря 2010

Проверяйте и сохраняйте размер файла каждый раз, когда вы читаете журнал, затем запустите программу чтения текста (или что вы используете) в этом месте при следующем чтении.

2 голосов
/ 01 декабря 2010

Если все, что вам нужно, это просматривать файл журнала в форме во время ее написания, почему бы не сделать что-то простое, например написать свой собственный Appender, который поддерживается TextBox, RichTextBox или чем-то еще.

Вот несколько ссылок, которые я нашел, просто делая быстрый поиск в Google по запросу «log4net textbox appender»:

http://www.nimblecoder.com/blog/archive/2009/01/30/using-a-delegate-and-custom-appender-with-log4net-to-display.aspx (Это выглядит довольно круто, потому что позволяет указать делегата для выполнения при каждом сообщении журнала, так что вы даже не будете привязаны к TextBox. Вы можете написать разные делегаты в зависимости от того, где вы хотел, чтобы выводился ваш журнал).

http://www.l4ndash.com/Log4NetMailArchive%2Ftabid%2F70%2Fforumid%2F1%2Fpostid%2F15133%2Fview%2Ftopic%2FDefault.aspx

http://weblogs.asp.net/psteele/archive/2010/01/25/live-capture-of-log4net-logging.aspx

http://www.l4ndash.com/Log4NetMailArchive%2Ftabid%2F70%2Fforumid%2F1%2Fpostid%2F14923%2Fview%2Ftopic%2FDefault.aspx (Этот Appender создает событие для каждого зарегистрированного сообщения).

http://markmail.org/message/ma62bdjpmab3cn7y (относительно недавно - опубликовано в 2008 году - использует RichTextBox для генерирования вывода в стиле ColoredConsoleAppender)

http://www.claassen.net/geek/blog/2005/06/log4net-scrollingtextbox.html (Этот использует MemoryAppender для захвата сообщений журнала и затем записывает эти сообщения в TextBox)

http://code.google.com/p/devdefined-tools/source/browse/trunk/projects/common/DevDefined.Common/Appenders/TextBoxAppender.cs?r=90

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

Некоторые общие темы, которые я заметил, кратко рассматривая эти Appenders:

  1. Когда вы пишете в TextBox из Appender, вам может понадобиться использовать BeginInvoke.

  2. Одна сложная часть, кажется, сообщает Appender, в какой TextBox писать. В большинстве случаев Appender настраивается с помощью файла конфигурации, а затем TextBox добавляется в Appender программным способом ПОСЛЕ инициализации системы ведения журнала (я думаю, что вам нужно либо получить хотя бы один регистратор, либо зарегистрировать хотя бы одно сообщение, чтобы заставить все ленивой инициализации произойти).

  3. Будьте осторожны с постоянным добавлением строк в TextBox. Вы можете использовать много памяти, вызвать проблемы с производительностью или превысить ограничение TextBox (если оно есть). Некоторые из этих Appenders содержат код, который периодически удаляет «старые» строки из TextBox.

2 голосов
/ 01 декабря 2010

Вы можете отслеживать индекс последнего символа, прочитанного из потока, и затем seek в эту позицию.

Редактирование: см. http://dotnetperls.com/seek для примеров.

...