Why is my c# paint method running out of memory?

只谈情不闲聊 提交于 2019-12-05 12:18:36

Just for anyone else, finding this page via Google:

A possible cause of System.OutOfMemoryException if you use System.Drawing.DrawArc could also be a bug if you try to print small angles.

For angles < 1 this bug occured several times in my code.

See also:

http://connect.microsoft.com/VisualStudio/feedback/details/121532/drawarc-out-of-memory-exception-on-small-arcs

Make sure that you dispose Pen and Brush objects as well and use using blocks to make sure that you dispose objects even if there are exceptions.

As a side note: avoid recreating and disposing _backBuffer each time you draw. Either catch resize event and dispose _backBuffer there or just check if _backBuffer has correct dimensions on each Paint event and dispose and recreate if dimensions does not match.

I didn't find anything horribly wrong with your code. Can you provide the exact line on which the OutOfMemoryException is happening?

Just so you know, that really took me a few months to understand: OutOfMemoryException doesn't mean out of memory. ;-) It happens in GDI+ when something simply went wrong (shows a bad coding style inside of the GDI, IMHO), like you tried to load an invalid image, or an image with invalid pixel format, etc.

Not really an answer to why, but a possible solution:

You shouldn't create a new bitmap every time. Just clear it everytime you draw a new frame.

You should however create a new bitmap when your size changes.

Why do you need a new bitmap every time you want something drawn with OnPaint?! You need exactly 1. Try something like this:

private Bitmap _backBuffer = new Bitmap(this.Width, this.Height);

protected override void OnPaint(PaintEventArgs e) { 

    Graphics g = Graphics.FromImage(_backBuffer);

    //Clear back buffer with white color...
    g.Clear(Color.White);

    //Draw all new stuff...
}

Not a answer to your question and maybe there is a good reason why you do it this way (I'd might learn something), but why create a bitmap first, draw on the bitmap and afterwards draw the bitmap on the form? Wouldn't it be more efficient to draw directly on the form? Something along the line of this:

protected override void OnPaint(PaintEventArgs e) {
    base.OnPaint(e);
    //_backBuffer = new Bitmap(this.Width, this.Height);
    Graphics g = Graphics.FromImage(_backBuffer);

    //Rest of your code
    //e.Graphics.DrawImageUnscaled(_backBuffer, 0, 0);

    //g.Dispose();
    //e.Dispose();
    //base.OnPaint(e);

    //_backBuffer.Dispose();
    //_backBuffer = null;
}

Also according to MSDN

When overriding OnPaint in a derived class, be sure to call the base class's OnPaint method so that registered delegates receive the event.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!