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. 日志滚动规则配置错误
如果你的日志文件是按规则自动滚动生成的,错误的滚动规则会导致每次写入都生成新文件:
- 检查日志框架配置,确认滚动触发条件为「按时间滚动」「按文件大小滚动」,而非每写入一条日志就滚动一次
- 检查日志文件名的模板,确保时间占位符是框架提供的动态变量,而非你自己定义的固定时间值(否则所有新生成的日志文件名都会使用同一个固定时间,出现重复/覆盖问题)
相关问题截图


内容的提问来源于stack exchange,提问作者illimite
相关产品推荐
相关产品推荐

