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

如何阻止System.Timers.Timer调用Stop方法后仍执行回调函数

System.Timers.Timer调用Stop后仍执行回调的解决方案

问题根本原因

System.Timers.Timer的Elapsed事件默认基于线程池调度触发,Stop()方法仅能阻止后续新生成的Elapsed事件,对于已经提交到线程池等待执行、或是已经在其他线程启动执行的回调逻辑,Stop()没有终止能力,这就是调用Stop方法后仍会触发回调的核心原因。

具体规避实现方案

  • 方案1:同步锁+停止标记双重校验(最常用,实现简单)
    单独声明布尔类型的停止标记,在回调入口和停止逻辑中加锁校验,避免多线程竞争导致的标记判断失效:

    private readonly object _timerLock = new object();
    private System.Timers.Timer _timer;
    private bool _isStopped = false;
    
    // Timer回调方法
    private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        lock (_timerLock)
        {
            // 只要标记为已停止,直接退出不执行业务逻辑
            if (_isStopped) return;
            
            // 此处写你的业务逻辑
        }
    }
    
    // 停止Timer的统一方法
    public void StopTimer()
    {
        lock (_timerLock)
        {
            _isStopped = true;
            _timer.Stop();
            _timer.Dispose();
        }
    }
    

    该方案可以100%避免停止后执行业务逻辑,即使有晚到的回调进入方法,也会被停止标记拦截直接返回。

  • 方案2:同步等待回调完成(适合需要确认回调完全执行完毕的场景)
    如果你需要确保调用停止后,所有正在执行的回调都已经跑完再走后续逻辑,可以用CountdownEvent做同步:

    private readonly CountdownEvent _callbackRunning = new CountdownEvent(1);
    private System.Timers.Timer _timer;
    
    private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {
            _callbackRunning.Reset();
            // 此处写你的业务逻辑
        }
        finally
        {
            // 无论业务逻辑是否抛出异常,都要发送完成信号
            _callbackRunning.Set();
        }
    }
    
    public void StopTimer()
    {
        _timer.Stop();
        _timer.Dispose();
        // 最多等待3秒,超时直接返回,可根据业务场景调整超时时间
        _callbackRunning.Wait(3000);
    }
    
  • 注意事项
    不要在Timer回调中执行超长阻塞逻辑,如果业务逻辑耗时较长,建议在逻辑中增加停止标记的轮询检查,方便停止触发时快速退出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 16:54:10