问题
I'm simply creating a Observable collection in Background and binding to it.
All objects inherit from INotifyPropertyChanged. but nevertheless the Memory consumption is continuously raising.
The following Objects instances are continuously raising
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
I'm using .net 4.5.2.
See also the following Screenshots:
MemoryConsumptionOverview
ClassesIncreasing
Attached the sample code
XAML Markup:
<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>
Code behind:
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:
It's caused by DispatcherTimer.
A DispatcherTimer will keep an object alive whenever the object's methods are bound to the timer. https://msdn.microsoft.com/ru-ru/library/system.windows.threading.dispatchertimer(v=vs.110).aspx
Use System.Timers.Timer instead and Dispatcher separately.
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();
});
}
来源:https://stackoverflow.com/questions/44821686/binding-wpf-datagrid-itemssource-creates-memory-leak