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

未注销DispatcherTimer的Tick事件为何会引发内存泄漏?

问题分析:DispatcherTimer导致WPF窗口内存泄漏的原因

你的核心认知误区是搞反了引用的主导方向——不是窗口持有Timer导致无法回收,而是WPF的Dispatcher持有Timer的强引用,Timer又反过来持有窗口的引用,形成了一条无法被GC打破的强引用链。

具体拆解引用关系:

  • Dispatcher持有Timer的强引用:当你调用timer.Start()后,WPF的UI线程Dispatcher(负责处理消息循环的核心组件)会将这个DispatcherTimer加入到内部的活动计时器列表中,并且保持强引用。只要Timer处于运行状态,Dispatcher就不会释放这个引用,Timer也就不会被GC回收。
  • Timer持有窗口的强引用:你给timer.Tick注册了窗口的UpdateTime方法,这个事件委托会捕获UpdateTime所属的窗口实例(因为UpdateTime是非静态方法),形成Timer到窗口的强引用。

为什么窗口无法被回收?

GC回收对象的前提是没有任何强引用指向该对象。现在的引用链是:
Dispatcher(UI线程核心) → DispatcherTimer → 事件委托 → Clock窗口实例
这条链上的所有对象都被强引用串联,即使你关闭了窗口,只要Dispatcher还在运行(比如应用程序未退出),整个链都无法被GC回收,窗口自然会滞留在内存中。

修复方案

在窗口关闭时,需要手动切断引用链:

protected override void OnClosed(EventArgs e)
{
    base.OnClosed(e);
    // 注销事件处理程序,切断Timer到窗口的引用
    timer.Tick -= UpdateTime;
    // 停止Timer,让Dispatcher释放对它的引用
    timer.Stop();
    // 清空窗口对Timer的引用
    timer = null;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 17:05:06