这是我第一次尝试对 .NET 应用程序进行内存分析(我已经完成了 CPU 调整),但我在这里遇到了一些问题。
我的应用程序中有一个视图,每页加载40张图片,每张图片大约为3MB。最多只有10页。考虑到我不想一次性在内存中保存400张图片或1.2GB的数据,因此在页面更改时将每个图像设置为 null。
起初,我认为可能只是我对这些图像的引用过期了。我下载了 ANTS Profiler(顺便说一句,这是一个很棒的工具),并运行了一些测试。对象生命周期图告诉我,除了父类中的单个引用(这也是按设计实现的,通过仔细检查我的代码得到证实)之外,我没有任何与这些图像相关的引用:
父类 SlideViewModelBase
会一直保留在缓存中,但当页面更改时,MacroImage
属性被设置为 null。我看不到任何这些对象应该比预期保留更长时间的迹象。
我接着查看了大对象堆和内存使用情况。在查看了三页图片后,我已经分配了691.9MB的非托管内存和442.3MB的 LOH 内存。来自我的 System.Drawing.Bitmap
到 BitmapImage
转换的 System.Byte[]
几乎占用了所有 LOH 空间。这是我的转换代码:
public static BitmapSource ToBmpSrc( this Bitmap b )
{
var bi = new BitmapImage();
var ms = new MemoryStream();
bi.CacheOption = BitmapCacheOption.OnLoad;
b.Save( ms, ImageFormat.Bmp );
ms.Position = 0;
bi.BeginInit();
ms.Seek( 0, SeekOrigin.Begin );
bi.StreamSource = ms;
bi.EndInit();
return bi;
}
我很难找到未经管理的内存去向。一开始我怀疑是System.Drawing.Bitmap
对象的问题,但是 ANTS 没有显示它们继续存在,而且我还运行了一个测试,确保全部对象都已被处理掉,但没有任何改变。因此,我仍未弄清楚这些未经管理的内存究竟来自哪里。
我的两个目前的理论是:
- LOH 内存碎片问题。如果我离开分页视图并点击几个按钮,约1.5GB的内存会被回收。虽然仍然太多,但还是引人入胜的。
- 某种奇怪的 WPF 绑定问题。我们使用数据绑定来显示这些图像,而我对这些 WPF 控件的详细工作原理并不是很熟悉。
如果有任何理论或分析提示,我将非常感激,因为(当然)我们面临着紧迫的最后期限,我正在努力完成这最后一部分工作。我觉得我已经被在 C++ 中追踪内存泄漏给惯坏了... 谁能想到呢?
如果您需要更多信息或者想让我尝试其他事情,请问我。很抱歉这里是一堵文字墙,我尽量让它简洁明了。
BitmapCacheOption.OnLoad
应该会清除流,我已经尝试手动处理它,但没有成功。谢谢你的回答,不过我应该在问题中添加这一点。 - Ed S.