Windows服务中System.Drawing上的Out of Memory异常

时间:2010-01-26 13:30:39

标签: graphics memory-management windows-services drawing system.drawing

我在Windows服务中密集使用system.drawing时出现内存不足的问题。

这是我的代码的一部分:

FileStream fs = new FileStream(ImagePath, FileMode.Open, FileAccess.Read);
img = (Image)Image.FromStream(fs).Clone();

这个例外不仅在这一点上提出,有时也会在涉及绘图,裁剪,调整大小,图像复制的其他方面提出异常

我总是处理所有使用过的物品。

我在system.drawing中看到了关于“Out of memory exception”的这篇文章 here

虽然它与我的情况非常相似但它是不同的,因为我的测试数据是一个包含40个图像的重复链,所以如果其中一个图像出现问题,它应该从第一个周期快速出现。

我看到了here

提到的限制

它说我们不应该在Win / Web服务上使用system.drawing。

好的,我需要将它与Windows服务一起用于大规模图像处理,有什么替代方案吗?

4 个答案:

答案 0 :(得分:1)

您正在调用的Image对象Clone未被处理(并且您的代码中可能存在其他类似错误)。这些对象消耗的内存仅在终结器运行后才会释放,这需要至少2个GC周期,OutOfMemoryException可能会在第一个GC上被抛出。
正确处理它应该类似于:

FileStream fs = new FileStream(ImagePath, FileMode.Open, FileAccess.Read);
using(var tmp = Image.FromStream(fs))
  img = (Image)tmp.Clone();
// dispose fs an img after use like usually

或者,您可以将整个文件读入MemoryStream并将其传递给Image.FromStream - 这意味着图像不会被解析两次,这样可以节省额外的资源。

答案 1 :(得分:0)

你为什么克隆图像?在您的示例中,您正在从文件中读取数据,然后创建副本。在具有高对象吞吐量的服务中抛出内存不足异常并不需要太多。

你可以这样做:

var img = Image.FromFile(ImagePath);

答案 2 :(得分:0)

你使用太多内存太快了,可能不会尽快释放它。

你需要重构你的代码,使你的资源更加保守,并确保你不会持有超过需要的大对象,并且你最早处理你的IDisposables。

这个过程并不容易,也不能在像这样的论坛中得到完全回答。

答案 3 :(得分:0)

这可能不相关,但......

我在使用C ++中的位图时遇到了问题,从较低级别的Windows API中获取了资源不足的错误。它似乎是由于Windows内部资源堆在使用bitblts等进行绘制时无法处理/分配位图/位图部分。

不知道链中的这类内容是否会使得dotnet库绊倒。 MSDN上有一个安装设备驱动程序的工具,可以用来检查各种桌面堆(不知道它与服务有什么关系。)我想(自从我使用它以来已经有一段时间了)它显示了使用的百分比/ available - 虽然这可能是一些指标,我怀疑这些区域的碎片也可能发生导致错误 - 遗憾的是我无法完全消除我的问题,但该工具可能会帮助您诊断您的问题。 (看起来这个工具可能被称为'dheapmon'。)