Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带有双缓冲图形的AccessViolationException_C#_.net_Winforms_Access Violation_Double Buffering - Fatal编程技术网

C# 带有双缓冲图形的AccessViolationException

C# 带有双缓冲图形的AccessViolationException,c#,.net,winforms,access-violation,double-buffering,C#,.net,Winforms,Access Violation,Double Buffering,正如标题所示,当我试图使用BufferedGraphics对象在.NET中绘制控件时,我遇到了AccessViolationException。这种情况会在一段时间后发生,或早或晚。评估对象的地址时,我注意到它随着程序的进行而不断增加。 我已经采取了一些措施来保存内存,这似乎有点帮助,但并没有最终解决问题。这个问题似乎与我是否在函数结束前处理图形对象无关 private void checkMemory() { long mem = GC.GetTotalMemo

正如标题所示,当我试图使用
BufferedGraphics
对象在.NET中绘制控件时,我遇到了AccessViolationException。这种情况会在一段时间后发生,或早或晚。评估对象的地址时,我注意到它随着程序的进行而不断增加。 我已经采取了一些措施来保存内存,这似乎有点帮助,但并没有最终解决问题。这个问题似乎与我是否在函数结束前处理图形对象无关

    private void checkMemory()
    {
        long mem = GC.GetTotalMemory(false);
        //Console.WriteLine("Allocated memory: " + mem.ToString());
        if (mem > criticalMemorySize) 
        {
            Console.WriteLine("GC started");
            GC.Collect(1, GCCollectionMode.Forced, true);
        }
    }

    BufferedGraphics graphics;

    protected override void OnPaint(PaintEventArgs e)
    {
        lock (e.Graphics)
        {
            base.OnPaint(e);
            checkMemory();
            if (e.ClipRectangle.Width * e.ClipRectangle.Height == 0)
                return;
            if (graphics == null || graphics.Graphics == null || graphics.Graphics.ClipBounds != e.ClipRectangle)
              graphics = _bufferedGraphicsContext.Allocate(e.Graphics, e.ClipRectangle);

            PaintBackground(graphics.Graphics);
            PaintHeader(graphics.Graphics);
            PaintBody(graphics.Graphics);
            DrawGrid(graphics.Graphics);
            //...

            graphics.Render(e.Graphics);
            graphics.Graphics.Dispose();
            graphics.Dispose();
        }
    }
调用
g.DrawString
时,此函数中出现异常:

    private void PaintBody(Graphics g)
    {
        Font seriffont = Design.CreateSerifFont(fontSize);
        Point mousePos = PointToClient(MousePosition);
        int hfeed = headHeight + headLineWidth - 2; //Dunno 
        for (int y = 0; y < LineCount; y++)
        {
            int vfeed = 0;
            for (int x = 0; x < ColumnCount; x++)
            {
                String s = "";
                Rectangle area = new Rectangle(vfeed, hfeed, colwidth, cellHeight);
                switch (_tableData[y][x])
                {
                    case ExBool.DontCare:
                        s = "*";
                        break;
                    case ExBool.False:
                        s = "0";
                        break;
                    case ExBool.True:
                        s = "1";
                        break;
                    default:
                        s = " ";
                        break;
                }
                Color backColor = cellBackColor;
                if (_activeHeaderColumn == x)
                {
                    backColor = cellActiveColColor;
                }
                if (area.Contains(mousePos))
                {
                    backColor = cellHoverColor;
                }
                if (area.Contains(mousePos) &&
                    ((MouseButtons & MouseButtons.Left) == MouseButtons.Left))
                {
                    backColor = cellActiveColor;
                }
                g.FillRectangle(new SolidBrush(backColor), area);
                g.DrawString(s, seriffont, Brushes.Black, area,
                    new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
                if (x != InputValues.Count() - 1)
                {
                    vfeed += lineWidth + colwidth;
                }
                else
                {
                    vfeed += typeSepLineWidth + colwidth;
                }
            }
            hfeed += cellHeight + lineWidth;
        }
    }
有人知道如何解决这个问题吗? 提前谢谢

编辑: 全局创建上下文变量,如下所示:

    BufferedGraphicsContext _bufferedGraphicsContext = new BufferedGraphicsContext()
对于经常使用
BufferedGraphics
的情况,文档中建议这样做。 这些函数是自定义控件的一部分,该控件允许用户输入二进制函数输入和输出。因为我不知道有任何类似的控件,所以我自己写了一个。 每当控件需要重新绘制时(例如,如果用户移动鼠标、单击某物等),都会调用上述函数,因为所有这些操作都需要视觉反馈。 一般来说,它可以按需要工作,除了在使用控件一段时间后发生的异常

编辑2:
由于异常几乎完全发生在
DrawString
函数上,那么NullReference(根据HResult,如果我没有弄错的话)是否可能不是由于绘图过程本身,而是由于某个参数或其他原因造成的?

这可能与您的情况不完全相同(我相信两年半后,这对你来说已经不现实了),但仍然如此

代码中有以下行:

Font seriffont = Design.CreateSerifFont(fontSize);
看起来这是你自己的代码,因为我在Google中找不到任何关于它的提及。下面是该方法的实现,它可能会导致你观察到的错误:

static class Design {
    static Font CreateSerifFont() {
        var fonts = new PrivateFontCollection();
        fonts.AddFontFile(@"c:\some_font.ttf");
        return new Font(fonts.Families[0], 12);        
    }
}
我想说的是,这是
PrivateFontCollection
的一个糟糕设计-它可以在它的
Font
仍在使用时进行处理,这将导致AccessViolationException。可以通过将
Font
从本地范围移动到类字段来修复上面的代码,类似这样:

static class Design {
    private static readonly PrivateFontCollection Fonts = new PrivateFontCollection();
    public  static readonly Font                  SerifFont;

    static Design() {
        Fonts.AddFontFile(@"c:\some_font.ttf");
        SerifFont = new Font(Fonts.Families[0], 12);
    }
}

请注意:
Graphics
对象不包含任何图形;它是一种工具,允许您在相关位图(包括控件的表面)上绘制。不要缓存“buffer”它。对于真正的双缓冲,您需要“buffer”位图。或者使用像PictureBox这样的双缓冲控件。-不确定是什么
\u bufferedGraphicsContext.AlloCATE 确实如此,但是如果它确实导致了E图形的处理,那么你就得到了你的例外。看起来我是在思考C++,试图写C语言。你不必管理图形对象。你甚至不必自己处理双缓冲(尽管在特殊情况下你可以证明它)。。强制GC是一个坏主意。如果你认为你需要这样做,那么你就有了一个严重的设计缺陷。感谢你迄今为止的关注。@TAW
Allocate
函数,如果我没有弄错的话,允许我创建一个
BufferedGraphics
对象,我可以将绘图函数应用到该对象上,然后将其渲染到t上当我完成时,他会显示实际的图形。我需要它来防止闪烁,这在异常发生之前确实可以很好地工作。我假设它在内部使用位图。如果我正确地调用了文档,我会按原样使用
BufferedGraphics
类,但我仍然无法解释为什么会有访问权限违反…@DonBoitnott我删除了GC位,因为它没有太大变化…我想你是对的,我只是以错误的方式想象它,但我找不到任何其他解释。手动双缓冲对我来说似乎是必要的,因为自动双缓冲不能防止大量闪烁,而这种方式看起来很不错在崩溃之前保持平滑一段时间。如果控制更大和/或迭代次数更多,这种情况会更快发生
static class Design {
    private static readonly PrivateFontCollection Fonts = new PrivateFontCollection();
    public  static readonly Font                  SerifFont;

    static Design() {
        Fonts.AddFontFile(@"c:\some_font.ttf");
        SerifFont = new Font(Fonts.Families[0], 12);
    }
}