Вопрос по wpf, memory-leaks, c#, xaml – Могут ли привязки создавать утечки памяти в WPF?

38

Нужно ли откреплять элементы, когда они исчезают, чтобы предотвратить утечки памяти? Я предполагаю, что я'Я просто немного обеспокоен тем, что если я перезагружаюсь и новый шаблон применяется к элементу управления, и в этом шаблоне существует привязка к внешнему элементу, может ли это помешать сборке мусора для элемента управления, созданного для шаблона?

Ваш Ответ

3   ответа
6

http://msdn.microsoft.com/en-us/library/aa970850.aspxWPF использует шаблоны слабых событий, которые не содержат сильных ссылок на объекты и позволяют им быть GC 'Ред, если они являются единственными ссылками на объект. "

Многие аспекты привязки данных WPF уже имеют слабый шаблон событий, применяемый при реализации событий ".

Слабые события используются только наDependencyProperties а такжеINotifyPropertyChanged объект, поэтому, если вы привязываете к POCO с режимом привязки, отличным отOneTime вы можете потерять память sa_ddam213
61

DependencyProperty или объект, который реализуетINotifyPropertyChanged тогда привязка может привести к утечке памяти, и вам придется отсоединять, когда вы закончите.

Это потому, что если объект не являетсяDependencyProperty или не реализуетINotifyPropertyChanged тогда он используетValueChanged событие черезPropertyDescriptors AddValueChanged метод. Это заставляет CLR создать сильную ссылку изPropertyDescriptor кobject и в большинстве случаев CLR будет сохранять ссылку наPropertyDescriptor в глобальной таблице.

Поскольку привязка должна продолжать прислушиваться к изменениям. Такое поведение поддерживает связь междуPropertyDescriptor иobject так как цель остается в использовании. Это может вызвать утечку памяти вobject и любойobject к которомуobject ссылается, это включает в себя цель привязки данных.

Короче говоря, если вы привязаны кDependencyProperty или жеINotifyPropertyChanged возражать, тогда вы должны быть в порядке, в противном случае, как любое подписанное событие, вы должны отменить подписку

Редактировать: Существует вероятность того, что это было исправлено в .NET4.5 с использованием слабых событий / ссылок, но после нескольких быстрых тестов мне это показалось тем же, мне придется углубиться в подробности, чтобы подтвердить, поэтому я 'лично скажу вможет быть исправить в 4.5 :)

Это гораздо лучший ответ - я узнал немного здесь jdphenix
@ sa_ddam213: и DP, и INotifyPropertyChanged точно безопасны. В любом случае, вы уверены в ПД? Я имею в виду, что все должно было получиться хорошо в последней платформе .Net 4.5, где интенсивно используется шаблон WeakEvent. Mario Vernari
Как насчет привязки к свойствам ReadOnly? Например, привязка к члену ExpressionBody? публичная строка Test => "TestString "; 3615
Можно ли просмотреть все привязки в визуальном дереве пользовательского элемента управления, определить, есть ли неправильный вид, и очистить их? Или почему бы не очистить все привязки независимо от их вида, используя BindingOperations.ClearBinding в событии unload. Или глуп по какой-то причине? FKDev
6

Finding Memory Leaks in WPF-based applications авторЙосеф Гольдберг, подробно описаны случаи, когда возможна утечка памяти в приложении WPF. Действительно, большинство из них относится к .NET 3.5 / 4.0, но некоторые случаи могут иметь отношение к этому дню. Кроме того, есть небольшойрасширение.

Цитата про утечку в:Binding

Cause:

Эта утечка задокументирована в этомкб статья, Это вызвано, потому что:

TextBlock элемент управления имеет привязку к объекту (myGrid), который имеет ссылку наTextBlock (это один из моих детейс).

Note: что этот тип утечки DataBinding является уникальным для конкретного сценария (а не для всех сценариев DataBinding), как описано вкб статья, Недвижимость в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}">
</textblock>

Fix/Workaround:

Есть несколько подходов, самый простой из них - просто очистить привязку, когда окна закрываются.

например.:

BindingOperations.ClearBinding(MyTextBlock, TextBlock.TextProperty);

Другой подход - установить режим привязки данных к OneTime. Увидетькб статья для других идей.

Полезная ссылка:

Предотвращение утечки памяти WPF с помощью DataBinding

Похожие вопросы