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

解决System.Timers.Timer调用间的延迟累积问题

解决计时器累积延迟并对齐系统整点分钟的方案

System.Timers.Timer 默认的循环计时(AutoReset=true)会因为每次触发后的处理耗时、系统调度延迟等因素,导致触发时间逐渐偏移,最终累积出明显误差。要让触发时间严格对齐系统时间的 HH:MM:00 时刻,不能依赖固定间隔的循环计时,而是需要每次动态计算下一个整点的触发间隔,改用一次性计时器实现。

核心思路

  • 禁用计时器的自动重置(AutoReset=false),每次触发完成后,重新计算下一个整点分钟的触发间隔
  • 基于当前系统时间,精准计算距离下一个 HH:MM:00 的毫秒数,确保每次触发都落在整点分钟上
  • 处理系统时间跳变的极端情况(比如手动调整系统时间),避免计时器出现异常

实现代码

private System.Timers.Timer _timer;

public void InitializeTimer()
{
    _timer = new System.Timers.Timer();
    _timer.AutoReset = false;
    _timer.Elapsed += OnTimerElapsed;
    
    // 计算初始延迟,启动第一次计时
    SetNextTimerTrigger();
}

private void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    try
    {
        // 执行OHLC数据存储的业务逻辑
        SaveOHLCDataToCSV();
    }
    finally
    {
        // 无论业务是否成功,都设置下一次触发
        SetNextTimerTrigger();
    }
}

private void SetNextTimerTrigger()
{
    var now = DateTime.Now;
    // 计算下一个整点分钟的时间:当前分钟+1,秒和毫秒置0
    var nextTrigger = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute + 1, 0);
    
    // 计算当前到nextTrigger的毫秒间隔
    var interval = (nextTrigger - now).TotalMilliseconds;
    
    // 处理极端情况:如果系统时间被往前调导致interval为负,或间隔异常,直接设置为60秒
    if (interval < 0 || interval > 60000)
    {
        interval = 60000;
    }
    
    _timer.Interval = interval;
    _timer.Start();
}

private void SaveOHLCDataToCSV()
{
    // 你的OHLC数据存储逻辑
}

关键细节说明

  • 使用finally块确保下一次触发:即使业务逻辑抛出异常,计时器也能继续运行,避免中断
  • 系统时间校准:通过动态计算间隔,每次都基于最新的系统时间,自动抵消累积延迟,同时处理系统时间调整的情况
  • 避免短间隔触发:当计算出的间隔过小时,直接设置为60秒,防止因为系统时间跳变导致频繁触发

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 09:40:28