dotMemory
告诉我(下面的截图," WPF绑定泄漏")绑定到字典时会出现内存泄漏,如下所示:
<ComboBox ItemsSource="{Binding Items, Mode=OneTime}"
DisplayMemberPath="Value"
SelectedValue="{Binding SelectedItem}"
SelectedValuePath="Key" />
问题1 ,对每个人:为什么是内存泄漏(我应该使用什么场景来解决问题)以及如何修复它?
对于dotMemory专家来说,Queston 2 :为什么如此基本的mvvm应用程序(见下文)报告了如此多的问题?我应该解决这些问题吗?怎么样?
MCVE(创建新的WPF解决方案,在xaml中使用上面的代码)代码背后:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string property = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
public Dictionary<string, string> Items { get; } = new Dictionary<string, string>
{
{ "1", "One" },
{ "1a", "One and a" },
{ "2a", "Two and a" },
};
string _selectedItem = "1a";
public string SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
OnPropertyChanged();
}
}
}
答案 0 :(得分:1)
绑定未实现的目标对象 INotifyPropertyChanged接口或不使用OneTime绑定 模式
回答1:
Xaml绑定到Dictionary,它是KeyValuePair的集合,它的Value属性被指定为DisplayMemberPath
的源。
暴露的KeyValuePair没有实现INotifyPropertyChanged接口,也无法为OneTime
指定DisplayMemberPath
绑定模式。因此,Dictionary的所有项目将永远留在记忆中。
回答2: dotMemory报告潜在的问题,只有你可以确定它是否是一个真正的问题。 不幸的是,.NET本身会生成字符串重复并创建一个永远不会被数据填充的数组,dotMemory也会报告它们,因为无法区分这些对象是否由&#34; user&#34;或者通过系统。 我建议你看看为什么你有最终的对象,似乎你忘记为某些对象调用IDisposable.Dispose方法。并检查这些未填充的数组是否由您创建。
答案 1 :(得分:0)
泄漏的原因是您绑定到未实现INotifyProperty更改的对象。
当我们绑定到字典的Value属性时,绑定目标将开始侦听属性更改通知。如果该属性不是 DependencyProperty 或实现 INotifyPropertyChanged 的对象,则WPF将诉诸于 System的 ValueChanged 事件。 .ComponentModel.PropertyDescriptor 类,用于在源对象的属性值更改时获取通知。
为什么这是个问题?好吧,由于运行时创建了对该PropertyDescriptor的引用,而该引用又引用了我们的源对象,并且运行时将永远不知道何时释放该初始引用(除非明确告知),因此PropertyDescriptor和我们的源对象都将保留在记忆。
通过绑定到 ObservableDictionary 来解决