BackgroundWorker & Timer, чтение только новых строк файла журнала?

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

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

Поэтому я создал 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!
}

EDIT: Code Solution (может быть, есть более элегантный способ?):

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;
}

person gremo    schedule 30.11.2010    source источник


Ответы (3)


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

person MusiGenesis    schedule 30.11.2010
comment
Я выбрал ваш путь, большое спасибо. Я отредактировал первый пост, чтобы включить кодовое решение. - person gremo; 01.12.2010

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

Изменить: см. примеры на http://dotnetperls.com/seek.

person TreDubZedd    schedule 30.11.2010

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

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

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.

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

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

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

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

person wageoghe    schedule 01.12.2010
comment
Ух ты. Я и забыл, насколько log4net усложняет простую задачу записи хрени в текстовый файл. :) - person MusiGenesis; 02.12.2010