You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Windows Forms应用中实现Serilog日志实时展示到WinForms控件的方案咨询

实现方案

直接开发自定义的Serilog Sink是最优方案,不需要轮询读取日志文件,日志输出时会直接推送到UI控件,完全实现实时展示。

步骤1:实现自定义Sink类

Serilog的Sink可以直接接收所有日志事件,我们只需要在Sink中完成日志格式化、跨线程UI更新的逻辑即可:

using Serilog.Core;
using Serilog.Events;
using System.Windows.Forms;

public class ListBoxSink : ILogEventSink
{
    private readonly ListBox _targetListBox;
    private readonly IFormatProvider _formatProvider;
    // 控制控件最多保留的日志条数,避免内容过多卡顿
    private const int MaxLogCount = 100;

    public ListBoxSink(ListBox targetListBox, IFormatProvider formatProvider = null)
    {
        _targetListBox = targetListBox ?? throw new ArgumentNullException(nameof(targetListBox));
        _formatProvider = formatProvider;
    }

    public void Emit(LogEvent logEvent)
    {
        // 格式化日志展示内容,可根据需求调整格式
        var logContent = logEvent.RenderMessage(_formatProvider);
        var displayText = $"[{logEvent.Timestamp:HH:mm:ss}] [{logEvent.Level}] {logContent}";
        // 日志输出线程可能不是UI线程,需要用Invoke安全更新控件
        if (_targetListBox.InvokeRequired)
        {
            _targetListBox.Invoke(new Action(() => AppendLog(displayText)));
            return;
        }
        AppendLog(displayText);
    }

    private void AppendLog(string displayText)
    {
        if (_targetListBox.Items.Count >= MaxLogCount)
        {
            _targetListBox.Items.RemoveAt(0);
        }
        _targetListBox.Items.Add(displayText);
        // 自动滚动到最新日志
        _targetListBox.SelectedIndex = _targetListBox.Items.Count - 1;
    }
}

步骤2:扩展Serilog配置方法

为了方便注册Sink,可以写个配置扩展方法:

using Serilog;
using Serilog.Configuration;
using System.Windows.Forms;

public static class ListBoxSinkExtensions
{
    public static LoggerConfiguration ListBox(
        this LoggerSinkConfiguration sinkConfig,
        ListBox targetListBox,
        IFormatProvider formatProvider = null,
        LogEventLevel minLevel = LogEventLevel.Verbose)
    {
        return sinkConfig.Sink(new ListBoxSink(targetListBox, formatProvider), minLevel);
    }
}

步骤3:在WinForms中注册Sink

要等主窗体的ListBox控件初始化完成后再配置Serilog,推荐写在主窗体的Load事件中:

private void MainForm_Load(object sender, EventArgs e)
{
    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Verbose()
        // 保留原有的文件写入Sink
        .WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day)
        // 新增ListBox输出Sink
        .WriteTo.ListBox(yourListBoxName)
        .CreateLogger();
}

可选调整

  • 只需要展示最近1-2条日志的话,把MaxLogCount参数改成对应数值即可
  • 需要过滤日志级别的话,注册Sink时传入minLevel参数,比如传LogEventLevel.Information就只会展示Info及以上级别的日志
  • 需要展示异常堆栈的话,在Emit方法中判断logEvent.Exception不为空时,把异常信息拼接到展示文本中即可

内容的提问来源于stack exchange,提问作者Fritz45

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 07:12:03