如何阻止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
相关产品推荐
相关产品推荐

