绑定可以在WPF中创建内存泄漏吗?

时间:2013-08-30 23:39:20

标签: c# wpf xaml memory-leaks

我是否需要在项目消失时取消绑定项目以防止内存泄漏?我想我只是有点担心,如果我重新加载并将新模板应用于控件,并且在该模板中存在与外部元素的绑定,是否可以阻止对模板的控制被垃圾收集?

3 个答案:

答案 0 :(得分:63)

如果您没有绑定DependencyProperty或实现INotifyPropertyChanged的对象,那么绑定可能会泄漏内存,并且您必须在完成后解除绑定。

这是因为如果对象不是DependencyProperty或未实现INotifyPropertyChanged,那么它会通过ValueChanged PropertyDescriptors方法使用AddValueChanged事件。这会导致CLR创建从PropertyDescriptorobject的强引用,并且在大多数情况下,CLR将在全局表中保留对PropertyDescriptor的引用。

因为绑定必须继续侦听更改。当目标保持使用时,此行为使引用在PropertyDescriptorobject之间保持活动状态。这可能导致object以及object引用的任何object内存泄漏,这包括数据绑定目标。

因此,如果您绑定到DependencyPropertyINotifyPropertyChanged对象,那么您应该没问题,否则就像任何订阅的事件一样,您应该取消订阅绑定


修改 有可能在.NET4.5中使用弱事件/参考文件修复了这个问题,但经过几次快速测试后对我来说似乎是一样的,我将不得不更深入地确认,所以我个人会说< strong>可能在4.5中修复:)

答案 1 :(得分:6)

http://msdn.microsoft.com/en-us/library/aa970850.aspx开始,WPF使用弱事件模式,它不包含对对象的强引用,如果它们是对象的唯一引用,则允许它们进行GC。

“WPF数据绑定的许多方面已经在事件的实现方式中应用了弱事件模式。”

答案 2 :(得分:6)

不要假装回答,仅供参考。在一篇关于Finding Memory Leaks in WPF-based applications作者 Jossef Goldberg 的经典文章中,详细描述了WPF应用程序中可能存在内存泄漏的情况。实际上,大多数都与.NET 3.5 / 4.0有关,但有些情况可能与今天有关。此外,还有一个小extension

引用Binding中的泄漏:

Cause:

kb article中记录了此泄漏。它被触发是因为:

TextBlock控件绑定到一个对象(myGrid),该对象的引用返回TextBlock(它是myGrid子节点之一)。

Note:这种类型的DataBinding泄漏对于特定方案(而不是所有DataBinding方案)是唯一的,如kb article中所述。 Path中的属性不是DependencyProperty,也不是实现INotifyPropertyChanged的类,此外还必须存在一系列强烈崇敬。

代码:

myDataBinding = new Binding("Children.Count");
myDataBinding.Source = myGrid; 
myDataBinding.Mode = BindingMode.OneWay;
MyTextBlock.SetBinding(TextBlock.TextProperty, myDataBinding);

同样的漏洞代码也可以用XAML编写:

<TextBlock Name="MyTextBlock" 
           Text="{Binding ElementName=myGrid, Path=Children.Count}" />

Fix/Workaround:

方法很少,最简单的方法就是在窗口即将关闭时清除绑定。

e.g:

BindingOperations.ClearBinding(MyTextBlock, TextBlock.TextProperty);

其他方法是将数据绑定模式设置为OneTime。有关其他想法,请参阅kb article

有用的链接:

Avoiding a WPF memory leak with DataBinding