You need to enable JavaScript to run this app. C# Windows服务定时器失效:启动即重复执行、后续不触发任务
优惠活动
大模型
产品
解决方案
定价
更多

C# Windows服务定时器失效:启动即重复执行、后续不触发任务

问题根因
  • 所谓“多线程重复执行”是日志写入逻辑的假象
    你定义的类级StringBuilder实例从未做过清空操作,所有追加的日志内容会一直累积在内存中;且每次写日志时,都会把当前StringBuilder中存储的全部历史内容追加到文件,而非只写本次新生成的日志行。
    按你当前代码的执行顺序,实际写日志的流程完全对应你看到的输出:
    1. OnStart开头往sb加第一行「Service started up」,把sb全部1行内容写入日志 → 产生日志第1行
    2. 调用CheckProcess,往sb加第二行「进程运行数量」,把sb全部2行内容写入日志 → 产生日志第2-3行
    3. CheckProcess判断后往sb加第三行「进程已运行」,把sb全部3行内容写入日志 → 产生日志第4-6行
    4. OnStart结尾往sb加第四行「Timer已设置」,把sb全部4行内容写入日志 → 产生日志第7-10行
      总共1+2+3+4=10行内容,和你贴出的日志行数、内容完全匹配。你贴出的日志所有条目的时间戳完全相同,也直接印证了不存在跨时间的多线程执行场景,所有重复内容都是同一时刻写入的历史日志。
  • 定时器无触发逻辑,导致程序“挂起”
    你初始化Timer实例后,从未给Elapsed事件绑定任何回调方法:
    • 你虽然定义了OnElapsedTime方法,但没有写timer.Elapsed += OnElapsedTime的绑定逻辑,定时器走完30秒间隔后找不到要执行的代码,自然不会产生任何新日志,表现为程序挂起。
    • 就算完成了事件绑定,当前OnElapsedTime方法里根本没有调用CheckProcess,触发后也不会执行进程检测逻辑。
  • 默认定时器机制和预期执行流程不匹配
    你使用的System.Timers.Timer默认开启AutoReset = true,触发逻辑是时间到了就立即触发事件,不管上一次的事件处理是否执行完成,天然存在多线程并发执行的风险,完全不符合你要的「单次检测执行完成后,再等待30秒启动下一次检测」的串行执行要求。且你没有任何重入保护,一旦绑定事件,很容易出现多线程同时检测、重复拉起进程的问题。
正确修复方向
  1. 修正日志写入逻辑:不要依赖累积的StringBuilder重复写历史内容,每次生成单条日志时即时写入文件,或在写完日志后主动清空StringBuilder,避免重复输出和内存累积。
  2. 适配串行执行的定时器逻辑:
    • 将定时器AutoReset属性设为false,即单次触发后自动停止计时
    • 把CheckProcess方法作为定时器的回调绑定到Elapsed事件上
    • 当CheckProcess执行完成后,再手动启动定时器开始下一次30秒倒计时,实现“执行完再等待”的预期流程
  3. 增加重入保护:使用原子操作标记当前检测逻辑是否在运行,若执行未完成则直接跳过本次触发,从机制上杜绝并发执行的风险。
  4. 完善停止逻辑:在OnStop事件中先停止定时器、释放资源,再置空引用,避免出现对象已释放的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 00:36:04