绑定到列表导致内存泄漏 [英] Binding to list causes memory leak

查看:180
本文介绍了绑定到列表导致内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我绑定一个ListBox的的ItemsSource到列表控件走后绑定引擎持有到列表中的元素。这将导致所有的列表元素留在内存中。使用ObservalbleCollection时,问题消失。为什么会这样?

When I bind an ItemsSource of a ListBox to a List the binding engine holds on to the list elements after the control is gone. This causes all the list elements to stay in memory. The problem goes away when using an ObservalbleCollection. Why does this happen?

窗口标签内的XAML

The xaml inside the window tag

<Grid>
    <StackPanel>
        <ContentControl Name="ContentControl">
            <ListBox ItemsSource="{Binding List, Mode=TwoWay}" DisplayMemberPath="Name"/>
        </ContentControl>
        <Button Click="Button_Click">GC</Button>
    </StackPanel>
</Grid>

背后code:

public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModel();
    }

private void Button_Click(object sender, RoutedEventArgs e)
    {
        this.DataContext = null;
        ContentControl.Content = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }

视图模型

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; }
}

编辑:要检查人istances的漏水,我用蚂蚁和.Net内存分析器。均表明力推GC-按钮仅绑定引擎是抱着参考人对象后。

To check the leaking of the person istances, I used ANTS and .Net memory profiler. Both show that after pushing the GC-button only the binding engine is holding reference to the person objects.

推荐答案

唉唉得了你。现在我明白你的意思了。

Ahhh got you. Now I understand what you mean.

您将内容设置为空,所以你杀compelte列表框,但仍然在的ItemsSource绑定到列表中,而ListBox的记忆没有完全释放出来。

You set the Content to null and so you kill the compelte ListBox but still the ItemsSource binds to List and so ListBox memory is not completely released.

这是不幸的是一个众所周知的问题,也有据可查的MSDN。

That is unfortunately a well known issue and also well documented on MSDN.

如果您不绑定到的DependencyProperty或实现INotifyPropertyChanged或的ObservableCollection那么绑定可以泄漏内存一个对象,你将不得不取消绑定,当你完成了。

If you are not binding to a DependencyProperty or a object that implements INotifyPropertyChanged or ObservableCollection then the binding can leak memory, and you will have to unbind when you are done.

这是因为,如果对象不是的DependencyProperty或者不实现INotifyPropertyChanged或不执行INotifyCollectionChanged(普通列表不实现此),那么它使用通过的PropertyDescriptor AddValueChanged方法ValueChanged事件。这将导致在CLR创建从的PropertyDescriptor到对象,并在大多数情况下,在CLR的强引用将保持在全局表中的的PropertyDescriptor参考。

This is because if the object is not a DependencyProperty or does not implement INotifyPropertyChanged or not implementing INotifyCollectionChanged (Normal list is not implementing this) 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.

由于绑定必须继续侦听的变化。此行为保持参考的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.

现在的问题是...是人实施INotifyPropertyChanged的?

The question is...is Person implementing INotifyPropertyChanged?

这篇关于绑定到列表导致内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆