2013-08-30 53 views
34

當物品消失以防止內存泄漏時,是否需要取消綁定物品?我想我只是有點擔心,如果我重新加載並將新模板應用於控件,並且在該模板中存在對外部元素的綁定,是否可以防止對模板進行的控制被垃圾收集?綁定可以在WPF中創建內存泄漏嗎?

回答

55

如果您沒有綁定到DependencyProperty或實現了INotifyPropertyChanged的對象,則綁定可能會泄漏內存,並且在完成後您將不得不解除綁定。

這是因爲,如果對象不是DependencyProperty或不實現INotifyPropertyChanged然後它使用通過PropertyDescriptorsAddValueChanged方法ValueChanged事件。這會導致CLR創建從PropertyDescriptorobject的強參考,並且在大多數情況下,CLR將在全局表中保留對PropertyDescriptor的引用。

因爲綁定必須繼續偵聽更改。當目標保持使用狀態時,此行爲將使參考在PropertyDescriptorobject之間保持活動狀態。這可能導致objectobject所引用的任何object內存泄漏,這包括數據綁定目標。

因此,在短期,如果你綁定到DependencyPropertyINotifyPropertyChanged對象,那麼你應該沒問題,否則像任何訂閱的情況下,您應該取消您的綁定


編輯: 有一種可能性,這在使用弱事件/參考的.NET4.5中修復了這個問題,但經過幾次快速測試後,我看起來也是如此,我將不得不更深入地進行確認,所以我個人認爲在可能會修復 4.5 :)

+1

這是一個更好的答案 - 我在這裏學到了很多東西 – jdphenix

+0

@ sa_ddam213:DP和INotifyPropertyChanged都是安全的。無論如何,你確定PD嗎?我的意思是,在最新的.Net 4.5框架中,WeakEvent模式被大量使用,這些事情應該已經變好了。 –

+0

我剛剛使用.NET4.5進行了檢查,當使用PropertyDescriptor時它似乎仍然泄漏,如果您想確認我使用了Jossef Goldberg的針對WPF測試的泄漏並重新編譯爲4.5,請鏈接:http://blogs.msdn.com /b/jgoldb/archive/2008/02/04/finding-memory-leaks-in-wpf-based-applications.aspx,我還沒有測試過4.5中的漏洞,因爲之前的框架版本中的綁定泄漏永久性地改變了我的WPF編碼習慣,以避免這個問題:),我希望它是固定的,我將在4.5以上添加免責聲明 –

6

http://msdn.microsoft.com/en-us/library/aa970850.aspx開始,WPF使用弱事件模式,它不包含對象的強引用,並且如果它們是對象的唯一引用,則它們將被GC'ed。

「WPF數據綁定的許多方面已經應用瞭如何實現事件的弱事件模式。」

+1

弱事件僅用於'DependencyProperties'和'INotifyPropertyChanged'對象,所以如果你比其他綁定模式綁定到POCO'OneTime'你可能最終泄漏內存 –

6

不要假裝回答,僅供參考。在關於Finding Memory Leaks in WPF-based applications作者Jossef Goldberg的經典文章中,詳細描述了在WPF應用程序中可能存在內存泄漏的情況。真的,大部分都與.NET 3.5/4.0有關,但有些情況可能與今天有關。另外,有一個小的extension

報價約泄漏Binding

Cause:

此泄漏在此kb article記錄。它被觸發是因爲:

TextBlock控件具有綁定到對象(myGrid),該對象具有返回到TextBlock(它是myGrid子項之一)的引用。

Note:此類型的DataBinding泄漏對於kb article中記錄的特定方案(而不是所有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}" /> 

Fix/Workaround:

有幾個方法,最簡單的一個是簡單地清除結合當窗戶即將關閉時。

例如爲:

BindingOperations.ClearBinding(MyTextBlock, TextBlock.TextProperty); 

另一種方法是設置數據綁定到一次性的模式。有關其他想法,請參閱kb article

有用的鏈接:

Avoiding a WPF memory leak with DataBinding