el-*_*ino 11 c# wpf garbage-collection finalizer memory-profiling
情况
我们正在运行一个大型WPF应用程序,它不会释放内存很长一段时间.它不是真正的内存泄漏,因为内存最终会被释放.我知道通常情况下,这不会被认为是一个问题.不幸的是,它与WPF指挥基础设施相结合成为一个性能问题.有关更详细的说明,请参见下文.
发现
我们有自动化测试,可以执行典型的用例.有些案例工作正常,并及时释放记忆.其他人正在占用内存,直到客户端最小化,打开一个新窗口或触发Gen2集合的其他一些条件.
•使用ANTS我们看到,对象没有GC Root,但是很多引用需要完成的其他对象.
•WinDbg未显示任何准备完成的对象.
•运行几个GC.Collect()
,GC.WaitForPendingFinalizers()
完全释放内存.
•我们知道哪种UI操作会导致高内存条件,但我们无法识别任何可疑代码.
题
我们希望有关于调试此类问题的任何建议.
WPF CommandManager背景
WPF CommandManager保存WeakReferences(_requerySuggestedHandlers
)的私有集合以引发CanExecuteChanged
事件.处理CanExecuteChanged
成本非常高(尤其是找到EventRoute CanExecute
,显然是一个RoutedEvent
).只要CommandManager感觉像是在执行命令就可以执行,它会遍历此集合并CanExecuteChanged
在相应的命令源上调用事件.
只要存在引用对象的GC句柄,就不会从该集合中删除WeakReferences.虽然尚未收集该对象,但CommandHelper会继续处理CanExecute
这些元素的事件(ButtonBase或MenuItems).如果存在大量垃圾(如我们的情况),这可能导致CanExecute事件处理程序的调用数量极大,这会导致应用程序非常滞后.
我的一个应用程序也有同样的问题。每次打开窗口时我都会调用:
GC.GetTotalMemory(true);
Run Code Online (Sandbox Code Playgroud)
这将强制 GC 立即清理内存,而无需等待。您可以在此处阅读有关此方法的更多信息:
http://msdn.microsoft.com/en-us/library/system.gc.gettotalmemory.aspx
关于调用 CanExecute 的问题,我尝试避免它们,因为同样的性能问题。相反,我在视图模型中使用属性,并将XAML 中的可视元素的IsEnabled属性绑定到视图模型中的属性。这样整体性能就提升了,CanExecute调用也没有了。
我希望这个能帮上忙。
归档时间: |
|
查看次数: |
1282 次 |
最近记录: |