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

未保存引用但已启用的System.Timers.Timer何时被视为垃圾回收?

未保存引用的System.Timers.Timer何时会被垃圾回收?

这是个很容易踩坑的问题,咱们结合你的代码场景一步步说清楚:

核心回收逻辑

当你创建System.Timers.Timer并设置Enabled = true时,.NET运行时会在内部维护一个对该Timer的强引用——只要Timer处于启用状态(或者说它的回调还有可能被触发),这个内部引用就会阻止垃圾回收器(GC)把它标记为垃圾。

你的代码场景分析

先看你这段代码:

public void TriggerUpdateStatus() {
    toolStripStatusLabel1.Text = "*";
    new Timer() { Interval = 1000, Enabled = true }.Elapsed += new ElapsedEventHandler(
        (object sender, ElapsedEventArgs args) => {
            toolStripStatusLabel1.Text = "";
            Timer t = ((System.Timers.Timer) sender);
            t.Stop();
            t.Dispose();//Is this needed?
        });
}

这个未保存引用的Timer的回收节点是这样的:

  1. 你创建Timer并启用后,内部强引用会留住它,确保它能活到Elapsed回调触发;
  2. 回调触发后,你调用了t.Stop()——这会让运行时移除内部的强引用;
  3. 当回调执行完毕时,局部变量t也会被销毁,此时这个Timer对象不再有任何存活的强引用;
  4. GC会在下一次回收周期里把它标记为垃圾并回收。

关于Dispose()的疑问

你问的t.Dispose();是否需要?答案是建议手动调用:

  • GC最终会通过终结器(Finalizer)处理Timer的非托管资源,但这个过程有延迟;
  • 手动调用Dispose()可以立即释放底层的计时器内核对象等资源,避免不必要的资源占用,尤其是在频繁触发这个方法的场景下,能更高效地管理资源。

额外补充:如果你的Timer没有手动调用Stop(),也没设置AutoReset = false,那它会一直处于启用状态,内部强引用永远存在,这个Timer永远不会被GC回收,直到你显式停止或释放它。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 19:42:28