【问题标题】:DrawText randomly gives error: Parameter is not validDrawText 随机给出错误:参数无效
【发布时间】:2017-05-10 15:12:05
【问题描述】:

我有一个错误:

参数无效。

此错误大约发生五分之一。

错误发生在这一行:

TextRenderer.DrawText(drawing, "Code12", font, fullWidthRectangle,
                                        textColor,
                                        flags);

小代码示例(非实际代码):

public Image CreateTripDetailPreview(Image image)
{
    using (var fontCollection = new PrivateFontCollection())
    using (var fontCollectionBold = new PrivateFontCollection())
    {
        fontCollection.AddFontFile("Assets\\SourceSansPro-Regular.ttf");
        fontCollectionBold.AddFontFile("Assets\\SourceSansPro-Bold.ttf");

        //This will be used to define heigt of text and allign text
        Rectangle fullWidthRectangle;

        var widthInDip = 360;
        var imgHeigtInDip = 168;
        var canvasWidth = 1080;
        var canvasHeight = 1200;
        var dip = canvasWidth / widthInDip;
        var leftRightMargin = 15 * dip;
        var resolutionScale = 5;

        using (Image img = new Bitmap(canvasWidth * resolutionScale, canvasHeight * resolutionScale))
         using (Graphics drawing = Graphics.FromImage(img))
         {
            //Clear 'background' and make it white
            drawing.Clear(Color.White);

            var imageHeight = (int)167.5 * dip;
            var height = imageHeight * resolutionScale;

            using (var cityImageBitmap = new Bitmap(image))
            using (var resizedCityImage = new Bitmap(cityImageBitmap, new Size(canvasWidth, imageHeight)))
            {
                canvasWidth *= resolutionScale;
                canvasHeight *= resolutionScale;
                dip *= resolutionScale;
                leftRightMargin *= resolutionScale;

                TextFormatFlags flags;
                using (var regularFont = new Font(fontCollection.Families[0], 1, FontStyle.Regular))
                using (var boldFont = new Font(fontCollectionBold.Families[0], 1, FontStyle.Regular)
                        ) //1 as default fontsize, fontsize will be calculated for each property
                {
                    Color textColor = Color.FromArgb(102, 102, 102);

                    //FlightCode
                    height += 4 * dip;
                    fullWidthRectangle = new Rectangle(leftRightMargin, height,
                    canvasWidth - leftRightMargin * 2,
                                    (int)22.5 * dip);
                    using (Font font = GetFontSizeByBox(drawing, "Code12",
                                    fullWidthRectangle.Size,
                                    regularFont))
                    {
                        flags = TextFormatFlags.NoPadding | TextFormatFlags.HorizontalCenter;
                        TextRenderer.DrawText(drawing, "Code12", font, fullWidthRectangle,
                                        textColor,
                                        flags);
                    }

                    using (var result = new Bitmap(img, canvasWidth / resolutionScale, canvasHeight / resolutionScale))
                    using (Graphics drawing2 = Graphics.FromImage(result))
                    {
                        drawing2.DrawImage(resizedCityImage, new Point(0, 0));
                        return new Bitmap(result);
                    }
                }
            }
        }
    }
}

GetFontSizeByBox 方法:

    private static Font GetFontSizeByBox(Graphics g, string longString, Size room, Font preferedFont, int extraSize = 0)
    {
        SizeF realSize = g.MeasureString(longString, preferedFont);
        var heightScaleRatio = room.Height / realSize.Height;
        var widthScaleRatio = room.Width / realSize.Width;
        var scaleRatio = heightScaleRatio < widthScaleRatio ? heightScaleRatio : widthScaleRatio;
        var scaleFontSize = preferedFont.Size * scaleRatio;
        return new Font(preferedFont.FontFamily, scaleFontSize + extraSize, preferedFont.Style);
    }

注意事项

  1. GC.Collect() 在这个方法的顶部解决了这个问题,我不希望使用这个“修复”来更好地防止它。
  2. 所有一次性的东西都在 using 语句中
  3. 该方法大部分时间都有效,1/5 次失败

发生错误时 DrawText 的值:

  • 图形对象(属性可访问)
  • “Code12”常规字符串
  • 字体Name = "Source Sans Pro" Size=179.088287(属性可访问)
  • 矩形X = 225 Y = 2565 Width = 4950 Height = 330
  • 颜色Name=ff666666, ARGB=(255, 102, 102, 102)
  • 标志TextFormatFlags.HorizontalCenter | TextFormatFlags.NoPadding

如果有人知道我为什么会收到此错误或如何修复它,我们将不胜感激。

【问题讨论】:

  • 调用TextRenderer.DrawText时检查参数的值?你得到了什么价值观?
  • @MightyBadaboom 在示例中它们总是相同的(并且失败了大约 1/5 次),因此不太可能是它的值。不过我会帮你查的
  • @MightyBadaboom 添加了值
  • 行中 var imageHeight = (int)167.5 * dip;和 canvasWidth - leftRightMargin * 2, (int)22.5 * dip);强制转换仅将值 167.5 和 22.5 转换为 int。也许您需要在整个表达式周围放置括号。例如 var imageHieght = (int)(167.5 * dip)。只是一个想法。
  • @dannyhut 倾角已经是一个整数了,你很好看!你的方式会更干净。遗憾的是错误仍然存​​在:(

标签: c# system.drawing


【解决方案1】:

好的,我找到了解决方案,正如 Hans Passant 所说,方法顶部的 GC.Collect(); 将解决问题。这确实有效,但我想找出原因。

代码的结构方式所有一次性对象将在方法完成后被释放(因为所有 using 语句),32bit 应用程序中有足够的内存来运行此方法一次或两次。但是,一旦调用该方法时仍然存在几代垃圾,它就会在制作位图时崩溃。

解决方案:
如果您遇到此问题并且不想在每次运行您的方法时强制进行垃圾收集,您可以设置一个阈值,如下所示:

if( Process.GetCurrentProcess().PrivateMemorySize64 > someNumber )
{
    GC.Collect();
}

结果这对我不起作用,因为每次都达到阈值,所以我每次都用GC.Collect(); 解决。如果有人有更好的解决方案(不增加内存),请不要犹豫。

【讨论】:

  • 内存不足并不会导致 GC 触发似乎很奇怪。我认为这就是它的工作原理。
  • @dannyhut 我也是这么认为的(以及这里的前辈)。但不知何故,这不会算作 GDI 创建位图?我不确定,发布我的发现是因为它可能对某人有所帮助;)
猜你喜欢
  • 2015-09-11
  • 2021-10-09
  • 2021-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-07
  • 1970-01-01
相关资源
最近更新 更多