.NET数据绑定和内存泄漏

时间:2013-02-13 23:22:52

标签: c# .net winforms profiler

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

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

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

.net memory profiler screenshot

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

如果您怀疑这是实际的内存泄漏,应用程序在打开和关闭显示大量数据的几个DataTableEditor后崩溃。此外,探查器告诉我对象已被处理,但仍然有对它的引用。

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

编辑:我想我知道泄漏可能来自哪里。上面的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()修复泄漏。这是我应该做的事情还是其他地方泄密的真正原因?

1 个答案:

答案 0 :(得分:1)

我相信你已经自己回答了记忆漏洞问题。

在我看来,泄漏的cource似乎是刷新按钮(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;
}

很难说你发现了这个问题的原因,但我会密切关注任何未被处置/释放/杀死的事件。

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