间歇性的System.Drawing/GDI+“通用”错误

4
我有一个ASPX页面,它将查询字符串中的任何内容呈现为垂直文本并返回PNG。它运作得很好。
我只有一个客户遇到了问题。每隔几天,该页面就会停止工作并抛出可怕的GDI+“通用”错误。
Error: System.Runtime.InteropServices.ExternalException (0x80004005): A generic error occurred in GDI+.
at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(Stream stream, ImageFormat format)
...

我不知道为什么会出现错误,也不知道它最终为什么消失了。 我向他们的安装中添加了一个测试ASPX文件,运行了类似的代码,进行了一些变化,以确定问题所在。 我发现如果将ImageFormat从Png更改为Jpeg,则错误会消失。
我可以考虑更改产品,以渲染JPEG而不是PNG。 但是,我无法知道这是否会像现在一样开始间歇性出错。
有人知道可能引起此类问题的原因吗? 谢谢! 以下是代码。
更新:客户服务器是运行IIS 7.5的Windows Server 2008 R2框,我的应用程序运行在.NET 4.0上。
    protected void Page_Load(object sender, EventArgs e)
    {
        byte[] image = GetImageBytes(this.Text);
        if (image != null)
        {
            Response.ClearContent();
            Response.ClearHeaders();
            Response.ContentType = "image/png";
            Response.OutputStream.Write(image, 0, image.Length);
        }
    }

    private byte[] GetImageBytes(string text)
    {
        var font = new Font("Tahoma", 11, FontStyle.Bold, GraphicsUnit.Pixel);

        // Create an image the size of the text we are writing
        Bitmap img = new Bitmap(1,1);
        var graphics = Graphics.FromImage(img);
        int width = (int)graphics.MeasureString(text, font).Width;
        int height = (int)graphics.MeasureString(text, font).Height;
        img = new Bitmap(img, new Size(width, height));

        // Draw the text onto the image
        graphics = Graphics.FromImage(img);
        graphics.Clear(Color.Transparent);
        graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
        graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
        graphics.DrawString(text, font, new SolidBrush(Color.Black), 0, 0);
        graphics.Flush();

        // Rotate the image to be vertical
        img.RotateFlip(RotateFlipType.Rotate270FlipNone);

        var stream = new System.IO.MemoryStream();
        img.Save(stream, ImageFormat.Png);
        stream.Position = 0;
        return stream.ToArray();
    }

1
这可能是一个有缺陷的显卡驱动程序。还要检查一下您是否已经用完了桌面堆栈。如果已满,则会在系统事件日志中写入事件日志条目。检查应用程序和系统事件日志以查找可疑事件。 - Alois Kraus
1
你可能应该释放字体、图像、图形和流对象。 - LarsTech
@LarsTech,确实,这就是为什么在我的回答中我建议使用新代码的原因 :) - Fredou
Alois,我会检查客户服务器的系统日志,谢谢。 - James Orr
我进行了进一步的测试 - 我将这段代码复制到一个控制台应用程序中,使用随机文本字符串生成许多图像。我停止了它在产生约300万张图片时没有出现任何问题。 - James Orr
1个回答

3

我认为刷新可能是问题所在

强制执行所有待处理的图形操作,并立即返回,而不等待操作完成。

此成员已重载。有关此成员的完整信息,包括语法、用法和示例,请单击重载列表中的名称。

您可以尝试这个来查看是否仍然存在该问题吗?

    private byte[] GetImageBytes(string text)
    {
        using (var font = new Font("Tahoma", 20, FontStyle.Bold, GraphicsUnit.Pixel))
        using (var img = new Bitmap(1, 1))
        {
            int width;
            int height;
            using (var graphics = Graphics.FromImage(img))
            {
                width = (int)graphics.MeasureString(text, font).Width;
                height = (int)graphics.MeasureString(text, font).Height;
            }
            using (var realImg = new Bitmap(img, new Size(width, height)))
            {
                using (var graphics = Graphics.FromImage(realImg))
                {
                    graphics.Clear(Color.Transparent);
                    graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                    graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                    graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                    graphics.DrawString(text, font, new SolidBrush(Color.Black), 0, 0);
                }

                realImg.RotateFlip(RotateFlipType.Rotate270FlipNone);

                using (var stream = new System.IO.MemoryStream())
                {
                    realImg.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
                    stream.Position = 0;
                    return stream.ToArray();
                }
            }
        }
    }

Fredou - 我使用了一个控制台应用程序在一个进程中运行代码数百万次,没有遇到任何问题。然而,这似乎是对代码的一个很好的改变。谢谢! - James Orr
抱歉,我刚注意到您还删除了使用语句中的Flush调用。我会尝试一下。 - James Orr
@BarryFandango,是的,我已经删除了它,因为我认为没有必要进行刷新调用,并且我还更新了我的代码,因为我忘记在图形上使用了“using”。 - Fredou
你没有释放图形对象。个人建议在打开流对象或进行RotateFlip调用之前关闭该图形对象。哦,你在我写这条评论后进行了一些编辑。 - LarsTech
@LarsTech,我注意到了并且6分钟前已经修复了它 :-) - Fredou

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