在将图像保存为PNG格式时出现GDI+异常

12
我的服务器上运行的ASP.NET应用程序在运行几天后开始抛出GDI+异常。重启服务器后,一切正常工作几天,然后突然再次发生此异常。在第一次发生后,每次尝试保存PNG图像时都会发生,直到我再次重新启动。
当我尝试将图像保存为JPEG时,它可以正常工作。
当我从我的项目中运行此代码时,它失败了:
var path = @"C:\Project\images\logo.png";
var image = Image.FromFile(path);

using (var ms = new MemoryStream())
{
    image.Save(ms, ImageFormat.Png);     // Fails here on GDI+ exception.
    //image.Save(ms, ImageFormat.Jpeg);  // JPEG works somehow
}

再次说明:当我重新启动远程桌面并运行此代码时,它能正常工作几天,但在某个时刻突然开始反复失败。

我尝试过:

  1. 使用相同的代码制作控制台应用程序,并在项目所在的RDP中运行它。它可以正常工作!

  2. 尝试了超过10篇文章中提到的很多不同变体的代码,但都无济于事。

  3. GCI.Collect()——无效。

  4. 检查所有具有写入权限的文件夹(也许是IIS的问题?)。

  5. 更多尝试。

我认为这应该是由于某些原因而突然更改了某些配置,但我无法理解可能是什么原因导致的。


1
那么异常具体是什么? - Evk
1
显然,如果它只是偶尔失败,那么这是一些我们永远无法复制的瞬态问题。不过你不需要任何代码 - 如果它已经是PNG格式,保存操作并没有什么作用。如果你想要将图像转换为字节,File.ReadAllBytes() 就足够了。 - Ňɏssa Pøngjǣrdenlarp
2
你是否正在处理所加载的图像?并且是否总体上处置了GDI资源? - usr
你是在异步上下文中执行这个操作吗? - TheZodchiy
@SimonMourier,我不确定我是否理解了你的意思,但如果我理解正确,那么我已经尝试过了,没有帮助。你能否在这里写一些代码来展示你的意思? - Misha Zaslavsky
显示剩余10条评论
3个回答

9
在我重新启动服务器后,一切都正常运行了几天,然后突然出现了这个异常。在第一次出现后,每次尝试保存PNG图像时都会出现,直到我再次重启。

听起来像是内存泄漏。这是编译到哪个.NET版本?这是在什么服务器操作系统上运行的?

您可以从将图像包含在using块中开始:

var path = @"C:\Project\images\logo.png";
using (Image image = Image.FromFile(path))
{
    using (var ms = new MemoryStream())
    {
        image.Save(ms, ImageFormat.Png);
    }
}

这个链接 我认为与您的情况相关。


3

因为您的对象未释放之一,所以它会引发GDI+错误,最好处理使用的对象。

如果您收到该错误,则我可以说您的应用程序在某个目录上没有写入权限。

GDI+将图像的高度限制为65534

始终优先使用using语句。即使代码抛出异常,也不会忘记释放对象。

var path = @"C:\Project\images\logo.png";
using (Image image = Image.FromFile(path))
{
      using (var ms = new MemoryStream())
      {
            image.Save(ms, ImageFormat.Png); //fails here on GDI+ exception.
            //image.Save(ms, ImageFormat.Jpeg); //Jpeg Works somehow
      }
}

FromFile方法会锁定文件,因此请使用Image.FromStream()方法来读取图像:

byte[] bytes = System.IO.File.ReadAllBytes(filename);
System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes);
using (var ms = new MemoryStream())
{
      image.Save(ms, ImageFormat.Png); //fails here on GDI+ exception.
      //image.Save(ms, ImageFormat.Jpeg); //Jpeg Works somehow
}

0

基本上,如果您有可丢弃的对象...请处理它们! 图像是可丢弃的,并且像位图一样使用Windows资源。 如果您不处理,Windows资源将在关闭应用程序之前不会被释放。因此,您需要处理任何实例化的图像。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接