在xaml窗口上调用ShowDialog时,如何防止调用垃圾收集?
我有一个使用大量内存的应用程序,但是现在我无法改变这个事实。 我的问题是我有一个我想要执行的操作并提供一个进度对话框但是看起来显示xaml进度窗口会导致GC.Collect
被调用10次! 任何想法如何优化打开我的进度窗口?
根据我的Ants Profiler,GC.Collect的调用是
System.Window.ShowDialog() -> .. .. System.Windows.Media.Imaging.BitmapSource.CreateCachedBitmap -> SafeMILHandle.UpdateEstimatedSize -> SafeMILHandleMemoryPressure.ctor -> MemoryPressure.Add -> MemoryPressure.ProcessAdd -> GC.Collect
还有一种解决方案可以完全禁用位图图像相关的内存压力和随后的垃圾收集。 它更像是一个黑客,但你可以在这里阅读类似的问题。
typeof(BitmapImage).Assembly.GetType("MS.Internal.MemoryPressure").GetField("_totalMemory", BindingFlags.NonPublic | BindingFlags.Static).SetValue(null, Int64.MinValue / 2);
这样您就可以避免在整个代码中搜索以查找和修改WPF图标初始化。 除此之外,一些控件如System.Windows.Forms.Integration.ElementHost
将隐式添加位图相关的内存压力,无论您如何初始化。
您是否检查过与该主题相关的其他stackoverflow问题? 您可以使用一些提示:
如何避免实时.NET应用程序中的垃圾收集?
这是WPF中的错误/function:
http://referencesource.microsoft.com/#PresentationCore/Core/CSharp/MS/Internal/MemoryPressure.cs
编辑:自.NET 4.6.2以来,MemoryPressure类已被删除。
垃圾收集是由WPF图标的初始化引起的。 当我从xaml中删除icon属性时:
而是在构造函数中初始化它:
public ProgressWindow() { InitializeComponent(); Icon = Properties.Resources.MyIcon.ToImageSource(); }
问题消失了。
在ShowDialog()
期间不再调用System.Window.UpdateIcon()
的区别。 UpdateIcon()
调用是为图标文件中的每个图像大小创建一个CachedBitmap
,而后者又调用了MemoryPressure.Add
并且由于应用程序的高内存使用率,因为每个新创建的位图都调用了GC.Collect
。
当在应用程序中加载大型项目时,这个小改动将我的进度对话框的加载时间减少了15秒!