Нужно ли отключать элементы, поскольку элемент исчезает, чтобы предотвратить утечку памяти? Наверное, я немного обеспокоен тем, что если я перезагрузился, и новый шаблон будет применен к элементу управления, и в этом шаблоне существует привязка к внешнему элементу, может ли это предотвратить блокирование элемента управления для сбора мусора?
Могут ли привязки создавать утечки памяти в WPF?
Ответ 1
Если вы не привязываетесь к DependencyProperty
или объекту, который реализует INotifyPropertyChanged
, тогда привязка может утечка памяти, и вам придется отменить привязку, когда вы закончите.
Это связано с тем, что если объект не является DependencyProperty
или не реализует INotifyPropertyChanged
, то он использует событие ValueChanged
с помощью метода PropertyDescriptors
AddValueChanged
. Это приводит к тому, что CLR создает сильную ссылку от PropertyDescriptor
до object
, и в большинстве случаев CLR будет хранить ссылку на PropertyDescriptor
в глобальной таблице.
Поскольку привязка должна продолжать прослушивать изменения. Это поведение сохраняет ссылку между PropertyDescriptor
и object
, поскольку цель остается в использовании. Это может привести к утечке памяти в object
и любом object
, к которому относится object
. Это включает в себя цель привязки данных.
Итак, если вы привязываетесь к объекту DependencyProperty
или INotifyPropertyChanged
, тогда вы должны быть в порядке, в противном случае, как и любое подписанное событие, вы должны отказаться от подписки на свои привязки
Edit: Возможно, это было исправлено в .NET4.5 с использованием слабых событий/ссылок, но после нескольких быстрых тестов мне показалось одинаковым, мне придется глубже погрузиться в подтверждение, поэтому я лично скажу в может фиксироваться в 4.5:)
Ответ 2
Из http://msdn.microsoft.com/en-us/library/aa970850.aspx WPF использует шаблоны слабых событий, которые не содержат сильных ссылок на объекты и позволяют им быть GC'ed if они являются единственными ссылками на объект.
"Многие аспекты привязки данных WPF уже имеют шаблон слабых событий, применяемый в том, как реализуются события."
Ответ 3
Не претендуйте на ответ, просто для справки. В классической статье на 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
не является a 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. См. Статью kb для других идей.
Полезная ссылка: