use*_*735 5 c# memory wpf binding memory-leaks
当我将ListBox的ItemsSource绑定到List时,绑定引擎在控件消失后保持列表元素.这会导致所有列表元素保留在内存中.使用ObservalbleCollection时问题就消失了.为什么会这样?
窗口标记内的xaml
<Grid>
<StackPanel>
<ContentControl Name="ContentControl">
<ListBox ItemsSource="{Binding List, Mode=TwoWay}" DisplayMemberPath="Name"/>
</ContentControl>
<Button Click="Button_Click">GC</Button>
</StackPanel>
</Grid>
Run Code Online (Sandbox Code Playgroud)
代码背后:
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.DataContext = null;
ContentControl.Content = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
Run Code Online (Sandbox Code Playgroud)
视图模型
class ViewModel : INotifyPropertyChanged
{
//Implementation of INotifyPropertyChanged ...
//Introducing ObservableCollection as type resolves the problem
private IEnumerable<Person> _list =
new List<Person> { new Person { Name = "one" }, new Person { Name = "two" } };
public IEnumerable<Person> List
{
get { return _list; }
set
{
_list = value;
RaisePropertyChanged("List");
}
}
class Person
{
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
编辑:为了检查人员泄漏,我使用了ANTS和.Net内存分析器.两者都显示在按下GC按钮后,只有绑定引擎保持对person对象的引用.
啊,你找到了 现在我明白你的意思了.
您将内容设置为null,因此您杀死强制ListBox但仍然将ItemsSource绑定到List,因此ListBox内存未完全释放.
遗憾的是,这是一个众所周知的问题,并且在MSDN上也有很好的记录.
如果您没有绑定到DependencyProperty或实现INotifyPropertyChanged或ObservableCollection的对象,则绑定可能会泄漏内存,并且您必须在完成后取消绑定.
这是因为如果对象不是DependencyProperty或者没有实现INotifyPropertyChanged或者没有实现INotifyCollectionChanged(Normal list没有实现它),那么它通过PropertyDescriptors AddValueChanged方法使用ValueChanged事件.这会导致CLR从PropertyDescriptor到对象创建强引用,并且在大多数情况下,CLR将在全局表中保留对PropertyDescriptor的引用.
因为绑定必须继续监听更改.当目标保持使用时,此行为使PropertyDescriptor和对象之间的引用保持活动状态.这可能导致对象中的内存泄漏以及对象引用的任何对象.
问题是......是实施INotifyPropertyChanged的人吗?
归档时间: |
|
查看次数: |
5558 次 |
最近记录: |