我的应用程序中有内存泄漏,我无法找到真正的来源。在名为DataTableEditor
的控件中有这行代码:
refreshButton.DataBindings.Add("Enabled", asyncSqlResultsViewer, "CanRefresh", true, DataSourceUpdateMode.Never);
asyncSqlResultsVewer
只是一个显示数据DataGridView
的用户控件。用于异步加载数据但不再存在。 DataTableEditor
控件是另一个包含AsyncSqlResultsVewer
的用户控件。泄漏似乎与此相关,因为它显示PropertyDescriptor
作为保持对象存活的路径的一部分:
我是使用.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()
修复泄漏。这是我应该做的事情还是其他地方泄密的真正原因?
答案 0 :(得分:1)
我相信你已经自己回答了记忆漏洞问题。
在我看来,泄漏的cource似乎是刷新按钮(ToolStripBindableButton
的实例)。
当调用ToolStripButton.Dispose()
时,它知道如何清理/释放所有需要的对象。但是,它无法知道你如何扩展课程,因此无法帮助你清理。
我希望ControlBindingsCollection
和BindingContext
继承IDisposable
,从而明确需要清理。
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing && dataBindings != null)
{
dataBindings.Clear();
}
dataBindings = null;
dindingContext = null;
PropertyChanged = null;
}
很难说你发现了这个问题的原因,但我会密切关注任何未被处置/释放/杀死的事件。
还要密切关注表单上的组件。如果使用IContainer实例创建,则只会自动处理,并且WinForms设计者可以选择不这样做。