当项目消失时,我需要取消绑定来预防内存泄漏吗?我想我只是有点担心,如果我重新加载并且在控件的新模板中应用了一个绑定到外部元素,那么这会阻止为该模板创建的控件被垃圾回收吗?
当项目消失时,我需要取消绑定来预防内存泄漏吗?我想我只是有点担心,如果我重新加载并且在控件的新模板中应用了一个绑定到外部元素,那么这会阻止为该模板创建的控件被垃圾回收吗?
如果您没有绑定到DependencyProperty
或实现了INotifyPropertyChanged
的对象,则绑定可能会泄漏内存,并且在完成后需要解除绑定。
这是因为,如果该对象不是DependencyProperty
或者没有实现INotifyPropertyChanged
,则它将通过PropertyDescriptors
的AddValueChanged
方法使用ValueChanged
事件。这会导致CLR从PropertyDescriptor
到object
创建一个强引用,并且在大多数情况下,CLR将在全局表中保留对PropertyDescriptor
的引用。
因为绑定必须继续监听更改。这种行为使得目标仍在使用时,保持PropertyDescriptor
与object
之间的引用活动。这可能会导致object
和任何object
引用的内存泄漏,包括数据绑定目标。
因此,简而言之,如果您绑定到DependencyProperty
或INotifyPropertyChanged
对象,则应该没问题,否则,就像订阅事件一样,您应该取消订阅绑定。
编辑: 有可能在.NET4.5中使用了Weak Events/References修复了此问题,但在快速测试后,我觉得情况仍然一样,我需要更深入地了解才能确认,所以我个人认为在4.5中可能已经修复了该问题 :)
本文仅供参考,不是答案。在经典文章Finding Memory Leaks in WPF-based applications
中,作者Jossef Goldberg详细描述了WPF应用程序中可能存在内存泄漏的情况。实际上,大多数情况涉及.NET 3.5/4.0,但有些情况可能至今仍然相关。此外,还有一个小的扩展。
引用关于Binding
泄漏的内容:
原因:
这个泄漏在这篇kb文章中有记录。它被触发是因为:
TextBlock
控件绑定到一个对象(myGrid),该对象又引用回TextBlock
(它是myGrid子对象之一)。
注意:
这种类型的DataBinding泄漏是特定场景下独特的(而不是所有DataBinding场景),如kb文章所述。在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}" />
修复/解决方法:
有几种方法可用,最简单的方法是在窗口即将关闭时清除绑定。
例如:
BindingOperations.ClearBinding(MyTextBlock, TextBlock.TextProperty);
另一种方法是将数据绑定的模式设置为 OneTime。请参见 kb文章 获取其他想法。
有用的链接:
但是,弱事件仅用于"WPF数据绑定的许多方面已经应用了弱事件模式来实现事件。"
DependencyProperties
和INotifyPropertyChanged
对象,因此如果您绑定到具有除OneTime
之外的绑定模式的POCO,则可能会导致内存泄漏。