【问题标题】:BackgroundWorker & Timer, reading only new lines of a log file?BackgroundWorker & Timer,只读取日志文件的新行?
【发布时间】:2011-05-18 03:26:21
【问题描述】:

我的应用程序写入一个日志文件(当前使用 log4net)。我想设置一个计时器和一个后台工作人员来读取日志文件并将其内容打印到我的表单中的某个控件中,同时它正在被写入。

我不能使用 FileSystemWatcher 类,因为它似乎坏了:有时“更改”事件会触发,有时不会。而且它的“池化率”极低。

所以我创建了一个 Timer 和一个 FileSystemWatcher。在计时器的“tick”事件中,后台工作人员完成其工作。

问题是:如何只读取自上次检查工人以来添加的行?

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

【问题讨论】:

    标签: c# timer log4net backgroundworker filesystemwatcher


    【解决方案1】:

    每次阅读日志时检查并存储文件大小,然后在下次阅读时在该位置启动文本阅读器(或您正在使用的任何东西)。

    【讨论】:

    • 我选择了你的方式,非常感谢。我已经编辑了第一篇文章以包含代码解决方案。
    【解决方案2】:

    您可以跟踪从流中读取的最后一个字符的索引,然后跟踪seek 到该位置。

    编辑:参见http://dotnetperls.com/seek 示例。

    【讨论】:

      【解决方案3】:

      如果您只想在表单上查看正在编写的日志文件,为什么不做一些简单的事情,比如编写您自己的由 TextBox、RichTextBox 或其他支持的 Appender。

      以下是我在 Google 上快速搜索“log4net textbox appender”时发现的一些链接:

      http://www.nimblecoder.com/blog/archive/2009/01/30/using-a-delegate-and-custom-appender-with-log4net-to-display.aspx(这个看起来很酷,因为它允许您指定要在每条日志消息上执行的委托,因此您甚至不会被绑定到文本框。您可以根据您想要日志的位置编写不同的委托输出去)。

      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

      我没有尝试过任何这些,所以我不能保证它们的质量。但是,我认为使用由 TextBox 支持的自定义 Appender 的方法似乎比尝试查看日志文件、阅读它然后将消息放入 TextBox 中更好的方法。

      我在简要查看这些 Appender 时注意到的一些常见主题:

      1. 当您从 Appender 写入 TextBox 时,您可能需要使用 BeginInvoke。

      2. 一个棘手的部分似乎是告诉 Appender 要写入哪个 TextBox。在大多数情况下,Appender 是通过配置文件配置的,然后在日志系统初始化之后,以编程方式将 TextBox 添加到 Appender(我认为您必须检索至少一个记录器或记录至少一条消息以强制所有发生延迟初始化)。

      3. 小心不断地向文本框添加行。您可能会占用大量内存、导致性能问题或超出 TextBox 的限制(如果有)。其中一些 Appender 包含定期从 TextBox 中删除“旧”行的代码。

      【讨论】:

      • 哇。我忘记了 log4net 使将废话写入文本文件的简单任务变得多么复杂。 :)
      猜你喜欢
      • 2019-03-15
      • 2018-11-09
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 2019-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多