.NET 数据绑定和内存泄漏

Posted

技术标签:

【中文标题】.NET 数据绑定和内存泄漏【英文标题】:.NET data bindings and memory leak 【发布时间】:2013-02-13 23:22:51 【问题描述】:

我的应用程序中存在内存泄漏,我找不到真正的来源。在名为DataTableEditor的控件中有这行代码:

refreshButton.DataBindings.Add("Enabled", asyncSqlResultsViewer, "CanRefresh", true, DataSourceUpdateMode.Never);

asyncSqlResultsVewer 只是一个带有显示数据的DataGridView 的用户控件。用于异步加载数据,但现在不再加载。 DataTableEditor 控件是另一个包含AsyncSqlResultsVewer 的用户控件。泄漏似乎与此有关,因为它显示 PropertyDescriptor 作为保持对象活动的路径的一部分:

我是使用 .NET Memory Profiler 的新手,但问题是,删除上面的行可以消除泄漏。使用DataBindings.Remove 删除边界也可以修复泄漏。但是,这应该发生吗? asyncSqlResultsVewer 已被处置,据我所知与DataTableEditor 一起被取消引用,因此只要没有其他人引用它们中的任何一个(对吗?),它们中的每个引用都不应该让它们继续存在。我仍然可以删除绑定以防万一或作为黑客攻击,但我希望有人帮助我找出泄漏的真正原因是什么。

如果您怀疑这是实际的内存泄漏,应用程序会在打开和关闭多个显示大量数据的DataTableEditors 后崩溃。此外,分析器告诉我该对象已被释放,但仍有对其的引用。

如果有任何其他信息可以帮助您解决这个问题,请告诉我。

编辑:我想我知道泄漏可能来自哪里。上面的refreshButton 是这个类的一个实例:

public class ToolStripBindableButton : ToolStripButton, IBindableComponent, INotifyPropertyChanged

    private ControlBindingsCollection dataBindings;

    private BindingContext bindingContext;

    public ControlBindingsCollection DataBindings
    
        get
        
            if (dataBindings == null) dataBindings = new ControlBindingsCollection(this);
            return dataBindings;
        
    

    public BindingContext BindingContext
    
        get
        
            if (bindingContext == null) bindingContext = new BindingContext();
            return bindingContext;
        
        set  bindingContext = value; 
    

    public override Image Image
    
        get  return base.Image; 
        set  SetImage(value); 
    

    private void SetImage(Image value)
    
        if (base.Image != value)
        
            base.Image = value;
            OnPropertyChanged(new PropertyChangedEventArgs("Image"));
        
    

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(PropertyChangedEventArgs e)
    
        if (PropertyChanged != null) PropertyChanged(this, e);
    

添加Dispose 覆盖并执行dataBindings.Clear() 可修复泄漏。这是我应该做的事情还是泄漏的真正原因仍在其他地方?

【问题讨论】:

如果您无法显示一些相关代码,这很难提供有效的答案..您是否有权访问相关源代码..? 我知道但不确定要显示什么 有太多可能与此相关的代码。 您正在添加绑定的 refreshButton 是否也超出范围并被释放?我想知道这是否是绑定本身的结果,因为有与之关联的事件,这将引用 DataGridView。 【参考方案1】:

我相信您已经自己回答了内存泄漏问题。

在我看来,泄漏的来源似乎刷新按钮(ToolStripBindableButton 的实例)。

ToolStripButton.Dispose() 被调用时,它知道如何清理/释放所有需要的对象。但是它无法知道你是如何扩展类的,因此它不能帮助你清理。

我本来希望 ControlBindingsCollectionBindingContext 继承 IDisposable 从而明确需要清理。

protected override void Dispose(bool disposing)

  base.Dispose(disposing);

  if (disposing && dataBindings != null)
  
    dataBindings.Clear();
  
  dataBindings = null;
  dindingContext = null;
  PropertyChanged = null;

很难说您是否找到了问题的根源,但我会密切关注任何未以某种方式处理/释放/杀死的事件。

还要密切关注表单上的组件。 Theise 只有在使用 IContainer 实例创建时才会自动处理,并且 WinForms 设计者可以选择不这样做。

【讨论】:

以上是关于.NET 数据绑定和内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

Silverlight + MVVM + 绑定 = 内存泄漏?

清理 JavaFX 属性侦听器和绑定(内存泄漏)

绑定会在 WPF 中造成内存泄漏吗?

NSViewController 如何避免绑定内存泄漏? [有示例应用程序]

AsyncSocket 和通知 - 内存泄漏

innerHTML引起IE的内存泄漏