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

Jam*_*eet 42 c# wpf xaml memory-leaks

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

sa_*_*213 68

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

这是因为如果对象不是DependencyProperty或者没有实现,INotifyPropertyChanged那么它ValueChanged通过该PropertyDescriptors AddValueChanged方法使用该事件.这使得CLR创建从一个强引用PropertyDescriptorobject,在大多数情况下,CLR将保持在参考PropertyDescriptor全局表.

因为绑定必须继续监听更改.此行为使目标保持在目标之间,PropertyDescriptor并且object目标仍在使用中.这可能会导致内存泄漏object和任何object给该object指,这包括数据绑定目标.

所以简而言之,如果你绑定到一个DependencyProperty或一个INotifyPropertyChanged对象那么你应该没问题,否则就像任何订阅的事件你应该取消订阅你的绑定


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

  • 绑定到 ReadOnly 属性怎么样?例如,绑定到ExpressionBody成员?公共字符串测试=>“TestString”; (2认同)
  • 注意:上述内存泄漏问题仅在绑定模式为 OneWay 或 TwoWay 时发生。如果绑定是 OneTime 或 OneWayToSource,并且绑定属性不是 DependencyProperty 或者绑定对象未实现 INotifyPropertyChanged,则 CLR 将不会创建强引用事件。 (2认同)
  • 它不是固定的。.NET Framework 4.7.1 具有相同的行为。 (2认同)

Ana*_*aev 7

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

关于泄漏的报价Binding:

Cause:

kb文章中记录了此泄漏.它被触发是因为:

TextBlock控制具有一个结合到一个对象(myGrid),其具有参考回TextBlock(它是myGrid儿童中的一个).

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

码:

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

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

<TextBlock Name="MyTextBlock" 
           Text="{Binding ElementName=myGrid, Path=Children.Count}" />
Run Code Online (Sandbox Code Playgroud)

Fix/Workaround:

有几种方法,最简单的方法是在窗口即将关闭时清除绑定.

例如:

BindingOperations.ClearBinding(MyTextBlock, TextBlock.TextProperty);
Run Code Online (Sandbox Code Playgroud)

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

有用的链接:

使用DataBinding避免WPF内存泄漏


jdp*_*nix 6

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

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

  • 弱事件仅用于 `DependencyProperties` 和 `INotifyPropertyChanged` 对象,因此如果您使用除 OneTime 之外的绑定模式绑定到 POCO,您最终可能会泄漏内存 (3认同)