绑定WPF DataGrid ItemsSource会造成内存泄漏

时间:2017-06-29 09:45:16

标签: wpf memory-leaks datagrid observablecollection inotifypropertychanged

我只是在后台创建一个Observable集合并绑定它。

所有对象都继承自INotifyPropertyChanged。 但是,记忆消耗不断提高。

以下对象实例不断提升

WeakReference                                                                                       
FrugalObjectList<WeakEventManager+Listener>                                                         
ConditionalWeakTable<TKey, TValue>+Entry<Object, Object>[]                                        
WeakEventTable+EventKey                                                                             
ConditionalWeakTable<Object, Object>                                                              
SingleItemList<WeakEventManager+Listener>                                                           
Object                                                                                              
Int32[]                                                                                             
WeakEventManager+ListenerList<NotifyCollectionChangedEventArgs>                                     
WeakEventManager+ListenerList<PropertyChangedEventArgs>                                             
HybridDictionary                                                                                    
ListDictionary                                                                                      
ListDictionary+DictionaryNode                                                                       
WeakEventManager+ListenerList<EventArgs>                                                            
WeakEventManager+ListenerList<CurrentChangingEventArgs>                                             
CollectionRecord                                                                                    

我正在使用.net 4.5.2。

另请参阅以下屏幕截图:

MemoryConsumptionOverview

ClassesIncreasing

附上示例代码

XAML加价:

<Window x:Class="BindingDataGridTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="120" Width="200"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <DataGrid ItemsSource="{Binding BindingVals, Mode=OneWay}" />
    </Grid>
</Window>

代码背后:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Threading;

namespace BindingDataGridTest
{
    public partial class MainWindow : INotifyPropertyChanged
    {

        public ObservableCollection<Values> BindingVals { get; set; }

        public MainWindow()
        {
            BindingVals = new ObservableCollection<Values>();
            InitializeComponent();

            DispatcherTimer myTimer = new DispatcherTimer { Interval = new TimeSpan(20) };
            myTimer.Tick += CreateVals;
            myTimer.Start();

        }
        private void CreateVals(object sender, EventArgs e)
        {
            Values myMainval = new Values
            {
                MyVal = "1V" + new Random().Next()
            };

            BindingVals.Clear();
            BindingVals.Add(myMainval);

            GC.Collect();
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

    public class Values : INotifyPropertyChanged
    {
        public string MyVal { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

    }

}

1 个答案:

答案 0 :(得分:0)

它是由DispatcherTimer引起的。

只要对象的方法绑定到计时器,DispatcherTimer就会使对象保持活动状态。 https://msdn.microsoft.com/ru-ru/library/system.windows.threading.dispatchertimer(v=vs.110).aspx

分别使用System.Timers.Timer和Dispatcher。

    public MainWindow()
    {
        BindingVals = new ObservableCollection<Values>();
        InitializeComponent();

        System.Timers.Timer myTimer = new Timer {Interval = 20};
        myTimer.Elapsed += CreateVals;
        myTimer.Start();

    }

    private void CreateVals(object sender, EventArgs e)
    {
        Dispatcher.Invoke(() =>
        {
            Values myMainval = new Values
            {
                MyVal = "1V" + new Random().Next()
            };

            BindingVals.Clear();
            BindingVals.Add(myMainval);

            GC.Collect();
        });

    }