在单个app实例中加载大量位图时WPF内存不足异常。有限制吗?

时间:2010-10-12 03:52:26

标签: c# wpf image memory

我需要将大量位图加载到内存中以便在WPF应用程序中显示(使用.net 4.0)。我遇到麻烦的地方是当我接近大约1,400MB的内存时(我从任务管理器的进程列表中得到这个)。

同样的事情发生在应用程序是在具有4GB内存还是6GB的计算机上运行(以及其他一些我没有详细信息的配置)。通过减少加载的图像以及它在1台机器上工作时很容易进行测试,然后它可以对它们进行全部工作,但是当它在一台机器上崩溃时它也可以在所有机器上运行。

当我减少图像数量并允许加载应用程序而不会导致内存异常时,我可以运行应用程序的多个实例(超过单个实例的1.4GB)而没有问题所以它似乎是每个实例的一些限制或者我的实例错误。

我将图像加载为BitmapImage,它们存储在List<BitmapImage>中或加载到List<byte[]>中,稍后在一堆分层序列中使用它们(使用Writeablebitmap

当我在使用中加载图像时发生错误。在可重复的情况下,我加载了600个640X640图像以及另外200-300个较小的图像,范围从100X100到200X200,尽管它似乎是一个整体位数问题。

所以我的问题是:

*在这种情况下,是否有一些内置的进程内存限制?

*是否有更好的技术可以将大量图像数据加载到内存中?

谢谢, 布赖恩

4 个答案:

答案 0 :(得分:11)

是的,每个进程内存分配都有一个限制。其中一个解决方案是让你的二进制LARGEADDRESSAWARE耗尽更多内存。

参考Out of memory? Easy ways to increase the memory available to your program,它就此解决方案进行了很好的讨论。

答案 1 :(得分:3)

下面可能是一个原因,但我不确定

问题不在于加载大量数据,而是因为CLR为大于85k内存的对象维护了一个大堆,并且你没有任何控制来释放这个大堆。

并且这些对象变为Long Lived,并且在Appdomain卸载时通常会解除分配。

我建议尝试在另一个AppDomain中加载更大的图像,并使用该appdomain来处理更大的图像。

See this MSDN Entry to Profiling GC

See if Memory Mapped Files helps in case you are using .net 4.0

And more example

答案 2 :(得分:1)

x86版本可以在64位Windows上访问4 GB,因此这是该过程的理论上限。这要求应用程序为large address aware。此外,.NET对单个对象施加了2 GB的限制。

您可能患有LOH碎片。大对象堆上存储的对象大于85000字节,这是托管堆的一个特殊部分,不会被压缩。

你说图像是600x600,但像素格式是什么,还有面具吗?如果每个颜色通道使用一个字节加上alpha通道的一个字节,则每个图像为600x600x32,因此在32位进程中尝试一次加载600个将是一个问题。

答案 3 :(得分:0)

您遇到限制32位进程,只能访问大约2Gb的数据。如果你要运行64位,你就不会有问题。 有很多方法可以解决这个问题,其中一些方法是:

  • 只是不加载那么多数据,只在需要时加载。使用缓存。
  • 使用内存映射文件将整个数据块映射到内存中。不建议使用,因为您必须自己完成所有内存管理。
  • 使用多个进程来保存数据并使用IPC机制仅提供您需要的数据,类似于第1项。