我在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服务一起用于大规模图像处理,有什么替代方案吗?
答案 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'。)