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

WPF DataGrid数据更新时出现内存泄漏问题求助

内存泄漏原因排查

  • 1 未冻结的SolidColorBrush实例无法回收:你每秒刷新时都会新建3个SolidColorBrush对象,该类继承自Freezable,未冻结的Freezable对象会关联当前UI线程的Dispatcher,且WPF绑定系统会对这类动态依赖对象创建强引用,导致GC无法回收,内存持续上涨。
  • 2 INotifyPropertyChanged未正确实现:Datos类虽然声明了PropertyChanged事件,但所有属性的setter都没有触发该事件,WPF针对未正确实现属性通知的绑定会生成强引用的绑定表达式,强持有Datos实例,无法被正常回收。
  • 3 多余的属性通知逻辑:ObservableCollection本身自带集合变更通知,Clear、Add操作会自动通知UI更新,手动触发Hmis的PropertyChanged属于多余操作,会产生额外的绑定更新开销,加重内存负担。
  • 4 额外优化点:DataGrid未开启UI虚拟化,每次集合变更都会生成新的行控件对象,也会增加不必要的内存占用。

可行解决方案

第一步 优化SolidColorBrush使用

优先预定义全局冻结的Brush实例,避免重复创建:

// 全局静态定义,只需创建一次
public static readonly Brush EstadoGreenBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF5DC75D"));
// 静态构造函数中冻结Brush
static MainWindow()
{
    EstadoGreenBrush.Freeze();
}

如果需要动态生成颜色,每次创建完SolidColorBrush后立即调用Freeze()方法:

var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF5DC75D"));
brush.Freeze();
dato1.Estado = brush;

第二步 修正Datos类的属性通知实现

所有属性的setter都触发PropertyChanged事件:

public class Datos : INotifyPropertyChanged
{
    private Brush _estado;
    public Brush Estado
    {
        get => _estado;
        set
        {
            _estado = value;
            OnPropertyChanged(nameof(Estado));
        }
    }

    private string _dato1;
    public string Dato1
    {
        get => _dato1;
        set
        {
            _dato1 = value;
            OnPropertyChanged(nameof(Dato1));
        }
    }

    private string _dato2;
    public string Dato2
    {
        get => _dato2;
        set
        {
            _dato2 = value;
            OnPropertyChanged(nameof(Dato2));
        }
    }

    public event PropertyChangedEventHandler? PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

第三步 移除多余代码

删掉ActualizacionUI_Tick方法中手动触发Hmis属性变更的代码:

// 删除这一行
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Hmis"));

第四步 开启DataGrid UI虚拟化(可选优化)

给XAML中的DataGrid添加虚拟化相关属性,复用行控件减少内存开销:

<DataGrid ItemsSource="{Binding Hmis, Mode=OneWay}" 
          AutoGenerateColumns="False" 
          IsReadOnly="True"
          EnableRowVirtualization="True"
          VirtualizingStackPanel.IsVirtualizing="True"
          VirtualizingStackPanel.VirtualizationMode="Recycling">

第五步 释放Timer资源(可选优化)

重写窗口的OnClosed方法释放Timer,避免Timer持有窗口引用导致窗口无法回收:

protected override void OnClosed(EventArgs e)
{
    base.OnClosed(e);
    timer?.Dispose();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 00:54:03