C# 绑定会在 WPF 中造成内存泄漏吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18542940/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can bindings create memory leaks in WPF?
提问by James Joshua Street
Do I need to unbind items as the item disappears in order to prevent memory leaks? I guess I'm just a little worried that if I reload and a new template is applied to a control, and in that template there exists a binding to an outside element, could that prevent the control made for the template from being garbage collected?
我是否需要在项目消失时解除绑定以防止内存泄漏?我想我只是有点担心,如果我重新加载并将新模板应用于控件,并且在该模板中存在与外部元素的绑定,是否会阻止为模板制作的控件被垃圾收集?
采纳答案by sa_ddam213
If you are not binding to a DependencyProperty
or a object that implements INotifyPropertyChanged
then the binding can leak memory, and you will have to unbind when you are done.
如果您没有绑定到一个DependencyProperty
或一个实现的对象,INotifyPropertyChanged
那么绑定可能会泄漏内存,并且您必须在完成后解除绑定。
This is because if the object is not a DependencyProperty
or does not implement INotifyPropertyChanged
then it uses the ValueChanged
event via the PropertyDescriptors
AddValueChanged
method. This causes the CLR to create a strong reference from the PropertyDescriptor
to the object
and in most cases the CLR will keep a reference to the PropertyDescriptor
in a global table.
这是因为如果对象不是 aDependencyProperty
或没有实现,INotifyPropertyChanged
则它ValueChanged
通过PropertyDescriptors
AddValueChanged
方法使用事件。这会导致 CLR 创建从PropertyDescriptor
到 的强引用,object
并且在大多数情况下,CLR 将PropertyDescriptor
在全局表中保留对 的引用。
Because the binding must continue to listen for changes. This behavior keeps the reference alive between the PropertyDescriptor
and the object
as the target remains in use. This can cause a memory leak in the object
and any object
to which the object
refers, This includes the data-binding target.
因为绑定必须继续监听变化。此行为使PropertyDescriptor
和之间的引用保持活动状态,object
因为目标仍在使用中。这可能会导致在内存泄漏object
和任何object
给该object
指,这包括数据绑定目标。
So in short if you are binding to a DependencyProperty
or INotifyPropertyChanged
object then you should be ok, otherwise like any subscribed event you should unsubscribe your bindings
所以简而言之,如果您绑定到一个DependencyProperty
或INotifyPropertyChanged
对象,那么您应该没问题,否则像任何订阅的事件一样,您应该取消订阅您的绑定
Edit:There is a possibility this was fixed in .NET4.5 using Weak Events/References, But after a few quick tests it seemed the same to me, I will have to dive in more deeply to confirm, so I'll personally say in mightbe fixed in 4.5 :)
编辑:有可能在 .NET4.5 中使用弱事件/引用修复了这个问题,但是经过几次快速测试后,我觉得还是一样,我将不得不更深入地进行确认,所以我个人会说in可能会在 4.5 中修复:)
回答by jdphenix
From http://msdn.microsoft.com/en-us/library/aa970850.aspx, WPF uses Weak Event Patterns, which do not hold strong references to objects and allow them to be GC'ed if they are the only references to an object.
从http://msdn.microsoft.com/en-us/library/aa970850.aspx,WPF 使用弱事件模式,它不持有对对象的强引用,如果它们是对一个东西。
"Many aspects of WPF data binding already have the weak event pattern applied in how the events are implemented."
“WPF 数据绑定的许多方面已经在事件的实现方式中应用了弱事件模式。”
回答by Anatoliy Nikolaev
Not pretend to answer, just for reference. In a classic article on Finding Memory Leaks in WPF-based applications
author Jossef Goldberg, described in detail cases, where there may be a memory leak in WPF application. Really, most relate to the .NET 3.5/4.0, but some cases may be relevant to this day. Also, have a small extension.
不假装回答,仅供参考。在Finding Memory Leaks in WPF-based applications
作者Jossef Goldberg的经典文章中,详细描述了 WPF 应用程序中可能存在内存泄漏的情况。确实,大多数都与 .NET 3.5/4.0 相关,但有些情况可能与今天有关。另外,有一个小的扩展名。
Quote about leak in Binding
:
关于泄漏的报价Binding
:
Cause:
Cause:
This leak documented in this kb article. It is triggered because:
这个泄漏记录在这篇知识库文章中。它被触发是因为:
The TextBlock
control has a binding to an object (myGrid) that has a reference back to the TextBlock
(it is one of myGrid children's).
该TextBlock
控件绑定到一个对象 (myGrid),该对象具有对TextBlock
(它是 myGrid 子项之一)的引用。
Note:
that this type of a DataBinding leak is unique to a specific scenario (and not to all DataBinding scenarios) as documented in the kb article. The property in the Path
is a not a DependencyProperty
and not on a class which implements INotifyPropertyChanged
and in addition a chain of strong reverences must exist.
Note:
这种类型的数据绑定泄漏对于特定场景(而不是所有数据绑定场景)是独一无二的,如知识库文章中所述。中的属性Path
是一个 not aDependencyProperty
和 not 在一个实现的类上INotifyPropertyChanged
,此外必须存在一系列强烈的尊重。
Code:
代码:
myDataBinding = new Binding("Children.Count");
myDataBinding.Source = myGrid;
myDataBinding.Mode = BindingMode.OneWay;
MyTextBlock.SetBinding(TextBlock.TextProperty, myDataBinding);
Same leaky code can be also written in XAML:
同样的泄漏代码也可以用 XAML 编写:
<TextBlock Name="MyTextBlock"
Text="{Binding ElementName=myGrid, Path=Children.Count}" />
Fix/Workaround:
Fix/Workaround:
There are few of approaches, the easiest one is simply to clear the binding when the windows is about to close.
有几种方法,最简单的方法是在窗口即将关闭时清除绑定。
e.g.:
例如:
BindingOperations.ClearBinding(MyTextBlock, TextBlock.TextProperty);
Other approach is to set the mode of the data binding to OneTime. See the kb articlefor other ideas.
另一种方法是将数据绑定的模式设置为 OneTime。有关其他想法,请参阅知识库文章。
Useful link:
有用的链接: