[英]Can bindings create memory leaks in WPF?
我是否需要在项目消失时解除绑定以防止内存泄漏? 我想我只是有点担心,如果我重新加载并将新模板应用于控件,并且在该模板中存在与外部元素的绑定,是否会阻止为模板制作的控件被垃圾收集?
如果您没有绑定到DependencyProperty
或实现INotifyPropertyChanged
的对象,则绑定可能会泄漏内存,并且您必须在完成后解除绑定。
这是因为如果对象不是DependencyProperty
或未实现INotifyPropertyChanged
则它会通过PropertyDescriptors
AddValueChanged
方法使用ValueChanged
事件。 这会导致 CLR 创建从PropertyDescriptor
到object
的强引用,并且在大多数情况下,CLR 将在全局表中保留对PropertyDescriptor
的引用。
因为绑定必须继续监听变化。 当目标仍在使用中时,此行为使PropertyDescriptor
和object
之间的引用保持活动状态。 这可能导致object
和object
引用的任何object
的内存泄漏,这包括数据绑定目标。
所以简而言之,如果您绑定到DependencyProperty
或INotifyPropertyChanged
对象,那么您应该没问题,否则像任何订阅的事件一样,您应该取消订阅您的绑定
编辑:有可能在 .NET4.5 中使用弱事件/引用修复了这个问题,但是经过几次快速测试后,我觉得还是一样,我将不得不更深入地进行确认,所以我个人会说in可能会在 4.5 中修复:)
不假装回答,仅供参考。 在一篇关于Finding Memory Leaks in WPF-based applications
的经典文章中,作者Jossef Goldberg详细描述了 WPF 应用程序中可能存在内存泄漏的情况。 确实,大多数都与 .NET 3.5/4.0 相关,但有些情况可能与今天有关。 另外,有一个小的扩展名。
关于Binding
泄漏的引用:
Cause:
这个泄漏记录在这篇知识库文章中。 它被触发是因为:
TextBlock
控件绑定到一个对象 (myGrid),该对象具有对TextBlock
的引用(它是 myGrid 子项之一)。
Note:
这种类型的数据绑定泄漏对于特定场景(而不是所有数据绑定场景)是独一无二的,如知识库文章中所述。 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:
有几种方法,最简单的方法是在窗口即将关闭时清除绑定。
例如:
BindingOperations.ClearBinding(MyTextBlock, TextBlock.TextProperty);
另一种方法是将数据绑定的模式设置为 OneTime。 有关其他想法,请参阅知识库文章。
有用的链接:
从http://msdn.microsoft.com/en-us/library/aa970850.aspx ,WPF 使用弱事件模式,它不持有对对象的强引用,如果它们是对一个东西。
“WPF 数据绑定的许多方面已经在事件的实现方式中应用了弱事件模式。”
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.