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

C# Windows Service 持续重复生成相同日志问题求解决方案

问题原因分析

你遇到的两个核心现象(固定时间戳、重复写入日志/生成重复文件)通常是几个常见的代码配置错误导致的,可按以下顺序排查:


1. 时间戳变量赋值位置错误

这是固定时间戳的最常见诱因:你把DateTime.Now/DateTime.UtcNow的赋值逻辑放在了服务启动的全局作用域、OnStart方法内或者日志循环外,整个服务运行周期内该变量只会在服务启动时赋值一次,后续所有日志调用都会复用这个固定时间值。
错误示例:

// 错误:全局变量仅在服务启动时赋值一次
private static readonly DateTime _logTimestamp = DateTime.Now;

public void WriteServiceLog(string content)
{
    File.AppendAllText("./service.log", $"{_logTimestamp:h:mm:ss tt} {content}{Environment.NewLine}");
}

修复方案:
每次写入日志时当场获取当前时间:

public void WriteServiceLog(string content)
{
    var currentTime = DateTime.Now;
    File.AppendAllText("./service.log", $"{currentTime:h:mm:ss tt} {content}{Environment.NewLine}");
}

如果使用NLog、Serilog等第三方日志框架,确保时间戳是由框架本身渲染,不要传入自定义的固定时间参数。


2. 定时任务重入导致重复写入

Windows服务通常用定时器触发周期性任务,若没有做重入控制,定时器会在上一次任务还未执行完成时触发下一次执行,若业务逻辑没有幂等处理,就会重复写入相同内容的日志。
常见的System.Timers.Timer重入问题修复方案:

private readonly object _taskLock = new object();
private System.Timers.Timer _serviceTimer;

protected override void OnStart(string[] args)
{
    _serviceTimer = new System.Timers.Timer(5000); // 示例为5秒执行一次
    _serviceTimer.Elapsed += DoPeriodicTask;
    _serviceTimer.AutoReset = false; // 禁止自动重复触发,执行完手动启动
    _serviceTimer.Start();
}

private void DoPeriodicTask(object sender, ElapsedEventArgs e)
{
    // 加锁避免极端情况下的重入
    lock(_taskLock)
    {
        // 业务逻辑+日志写入
        WriteServiceLog("定时任务执行完成");
        
        // 执行完成后再启动下一次计时
        _serviceTimer.Start();
    }
}

3. 日志滚动规则配置错误

如果你的日志文件是按规则自动滚动生成的,错误的滚动规则会导致每次写入都生成新文件:

  • 检查日志框架配置,确认滚动触发条件为「按时间滚动」「按文件大小滚动」,而非每写入一条日志就滚动一次
  • 检查日志文件名的模板,确保时间占位符是框架提供的动态变量,而非你自己定义的固定时间值(否则所有新生成的日志文件名都会使用同一个固定时间,出现重复/覆盖问题)

相关问题截图

问题截图1
问题截图2

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 11:45:04