【问题标题】:Intermittent System.Drawing/GDI+ "Generic" Error间歇性 System.Drawing/GDI+“通用”错误
【发布时间】:2013-07-12 02:49:12
【问题描述】:

我有一个 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();
    }

【问题讨论】:

  • 这可能是一个有问题的显卡驱动程序。还要检查您是否已用完桌面堆。如果已满,则会在系统事件日志中写入一个事件日志条目。检查应用程序和系统事件日志中是否存在可疑事件。
  • 您可能应该处理字体、img、图形和流对象。
  • @LarsTech,这就是我在回答中建议新代码的原因:)
  • 阿洛伊斯,我会检查客户服务器的系统日志,谢谢。
  • 我做了一些进一步的测试 - 我将此代码复制到一个控制台应用程序中,该应用程序使用随机文本字符串生成许多图像。我把它停在了大约 300 万张没有问题的图像上。

标签: c# asp.net system.drawing


【解决方案1】:

I would say that the flush could be the issue

强制执行所有挂起的图形操作并立即返回,无需等待操作完成。

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

你可以试试这个看看你是否还有问题?

    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 - 我使用控制台应用程序在一个进程中运行代码数百万次,但没有遇到任何问题。但是,无论如何,这似乎对代码进行了很好的更改。谢谢!
  • 抱歉,刚刚注意到您还删除了对 Flush 的调用以及 using 语句。我会试试看。
  • @BarryFandango,是的,我删除了它,因为我没有看到需要该刷新调用,并且我还更新了我的代码,因为我忘记在图形上使用了
  • 您没有处理图形对象。就个人而言,我会在打开该流对象或 RotateFlip 调用之前关闭该图形对象。啊啊啊,自从我写了这篇评论后,你做了一些修改。
  • @LarsTech,我注意到了,并在 6 分钟前修复了它:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-27
  • 2016-05-20
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多