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

关于C#中Timers.Timer类多定时器使用的三个技术问题

关于C# Timers.Timer的三个问题解答

问题1:在定时器事件触发前重新执行m_Timer = new Timer(...)会产生什么结果?

  • 原Timer对象会失去引用,但它的回调仍可能触发:定时器由线程池调度,只要未被Dispose,即便你已无引用,到触发时间回调依然会执行。
  • 旧定时器变成“无主”状态:你无法再控制它(停止、Dispose),只能等待GC回收,这会造成不必要的资源占用,甚至引发逻辑错误(比如旧回调在新定时器创建后仍执行,干扰当前业务逻辑)。

问题2:C#是否有内置方法处理这种情况?需要用List管理吗?

  • 单个定时器场景无需用List,直接利用IDisposable接口即可:Timers.Timer实现了IDisposable,创建新定时器前,先对旧定时器执行Dispose操作,就能安全清理资源并停止回调。修正后的示例代码:
public void MyEventNotification(in MyEventInfo ei)
{
    if (ei.State != MyEventState.Completed)
    {
        // 先清理旧定时器
        m_Timer?.Dispose();
        // 注意:ei.StringID无需new,直接传递即可
        m_Timer = new Timer(TimerHandler, ei.StringID, 1000, Timeout.Infinite);
    }
}
  • 仅当需要同时管理多个独立定时器时,才需要用集合(比如List<Timer>)跟踪,此时要注意线程安全,清理时需遍历集合对每个定时器执行Dispose。

问题3:将定时器加入List后,能否在TimerHandler中移除自身?

  • 可以,但必须注意线程安全:Timer的回调在ThreadPool线程执行,若添加/移除List的操作在其他线程(比如调用MyEventNotification的线程)同时进行,会引发线程冲突。
  • 正确实现方式:
    1. 使用线程安全集合,比如ConcurrentBag<Timer>,它自带线程安全的添加/移除方法;
    2. 若用普通List<Timer>,需在操作List时加lock保护;
    3. 移除前先Dispose当前定时器,避免后续回调触发。示例代码:
// 定义锁对象和List
private readonly object _timerLock = new object();
private List<Timer> _timerList = new List<Timer>();

public void TimerHandler(Object stateinfo)
{
    string id = (string)stateinfo;
    // 加锁操作List,确保线程安全
    lock (_timerLock)
    {
        var currentTimer = _timerList.FirstOrDefault(t => /* 根据stateinfo或标识匹配当前定时器 */);
        if (currentTimer != null)
        {
            currentTimer.Dispose();
            _timerList.Remove(currentTimer);
        }
    }
}

额外代码修正提示

  • 原代码中new ei.StringID是错误写法,直接传ei.StringID即可(它本身已是字符串类型);
  • 访问m_JustForShow时要注意线程安全:若该字段会被多线程(主线程、定时器回调线程)修改/读取,需用volatile修饰或加lock,避免内存可见性问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:56:29