c# – WPF GarbageCollection中的高级调试建议

前端之家收集整理的这篇文章主要介绍了c# – WPF GarbageCollection中的高级调试建议前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
情况

我们正在运行一个不会释放内存的大型WPF应用程序.它不是真正的内存泄漏,因为内存将最终被释放.我知道通常情况下,这不会被认为是一个问题.不幸的是,它与WPF命令基础结构一起成为一个性能问题.有关详细信息,请参见下文.

发现

我们有自动测试,可以执行典型的用例.有些情况正常,正在及时释放记忆.其他人正在占用内存,直到客户端被最小化,打开了一个新的窗口或者触发Gen2集合的其他一些条件.

•使用ANTS,我们看到,对象没有GC根,但是对其他需要完成的对象的引用很多.

•WinDbg没有显示任何对象准备好完成.

•运行几个GC.Collect(),GC.WaitForPendingFinalizers()完全释放内存.

•我们知道哪个UI操作会导致高内存条件,但是我们无法识别任何可疑的代码.

我们非常感谢任何关于调试这个问题的建议.

WPF CommandManager背景

WPF CommandManager包含用于提升CanExecuteChanged事件的WeakReferences(_requerySuggestedHandlers)的私有集合.处理CanExecuteChanged是非常昂贵的(特别是找到CanExecute的EventRoute,这显然是一个RoutedEvent).每当CommandManager感觉如果可以执行命令时,它会重新查询,它会遍历此集合并调用相应命令源上的CanExecuteChanged事件.

只要有引用对象的GC句柄,WeakReferences不会从该集合中删除.当对象尚未被收集时,CommandHelper会继续处理这些元素(ButtonBase或MenuItems)的CanExecute事件.如果有很多垃圾(在我们的情况下),这可能会导致非常大量的调用CanExecute事件处理程序,这导致应用程序真的滞后.

解决方法

我的一个应用程序也有同样的问题.在窗口的每一个开口我叫:
GC.GetTotalMemory(true);

这将迫使GC立即清理内存而无需等待.您可以在这里阅读更多关于此方法

http://msdn.microsoft.com/en-us/library/system.gc.gettotalmemory.aspx

关于调用CanExecute的问题,我试图避免由于性能问题相同.相反,我在我的视图模型中使用属性,并将视觉元素的IsEnabled属性从XAML绑定到视图模型中的属性.以这种方式,整体性能得到改善,CanExecute呼叫已经消失.

我希望这将有所帮助.

猜你在找的C#相关文章