开发者

System.Drawing Out of Memory Exception

My application graphics engine throws these exceptions. They are all consumed by an empty catch block. In the early days I found one that was not trapped (associated with pen widening as I recall). I开发者_如何学编程 surrounded it with try and an empty catch block. It seems that these exceptions have no effect on the drawing produced. I have done some reading on this without really understanding or getting to the bottom of it.

So to my questions:

  1. Why would these be thrown if they can be consumed safely? and
  2. Is it safe to ignore them? I worry that each one is having some hidden effect. I have memory leaks which I have never found for example.


I've seen System.Drawing throw OutOfMemoryExceptions even when it's not out of memory. Some GDI+ function is apparently just returning a stupid error code.

IIRC, you will get an OutOfMemoryException if you try to use a LinearGradientBrush to fill a rectangle whose width or height is zero. There may be other conditions too, but this is the main one we ran into.

In that case, there's no need for a try/catch. Just add an if statement to your drawing code, and don't fill the rectangle if the width or height is zero.

Update: According to the comments on this answer, it can also occur if you try to load a corrupted image file. For that, you would have no choice but to do try/catch.

You're probably safe catching OutOfMemoryExceptions from GDI+, but keep the try blocks as small as possible. Consider logging the exceptions, so you can analyze the logs and add defensive code where possible. You don't want to mask a real OutOfMemoryException, but you don't want a stupid GDI+ error code to crash your app either.


It's a pretty bad exception: http://msdn.microsoft.com/en-us/library/system.outofmemoryexception.aspx .. not enough memory to continue execution of the program.

You'll often find if you have so much allocated that 'simple' operations/allocations throw this message, the app will crash soon after. If it's one massive allocation that's failing, you may be able to continue.

If the app does anything important, you should try to close things down gracefully.

To explicitly answer your questions:

  1. They're thrown so the app has a chance to react/recover: some memory allocations (10GB worth of objects) might be expected to fail in many situations, perhaps a one-line app crash (int[] x = new int[5368709120]; equivalent) should really throw an exception rather than crash everything

  2. There should be no hidden effect, but if one allocation fails, then perhaps the next time you want a string or other useful object in some small way allocated for general operation of the app: things might become unstable. That said depending on the environment, you might get this exception at any time..

Edit: Anyone reading this should also consider that apparently GDI+ throws this exception for other reasons too.


I tried the solution 'Joe White' suggested and that was it. It threw a OutOfMemoryException because the rectangle's width and height were 0. In my case the window was minimized when the exception occurred.

Here is an example;

  Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)

    Using e
        ##Add conditions to avoid OutOfMemoryException##
        If (Not ClientRectangle.Width = 0) And (Not ClientRectangle.Height = 0) Then
            Using rect As GraphicsPath = New GraphicsPath()
                rect.AddRectangle(ClientRectangle)

                Using gb As New PathGradientBrush(rect)
                    gb.WrapMode = WrapMode.Tile
                    gb.SurroundColors = New Color() {GradientColors(1), GradientColors(0), GradientColors(2)}
                    gb.CenterColor = GradientColors(0)
                    gb.SetSigmaBellShape(0.5F)
                    e.Graphics.FillPath(gb, rect)
                End Using
            End Using
        End If
    End Using

End Sub


I had this line of code:

bgpart = Primary.BackGround.Clone(rect, Primary.BackGround.PixelFormat);

That actually copies a part of the existing background. The purpose was to copy the part of the background my starship was drawn on, so the starship can be moved and, each time, the proper background to be drawn. Simply put, 'something' moves on a standard background, and the background remains.

Then this 'Out of memory' error of system.drawing start to manifest sometimes. When i focus on it, i realize that it has nothing to do with use up all memory. It should be called 'Out of memory RANGE', because what i found out is that on error cases, where i manage to emulate exactly, i asked him to read an image part that was actually outside the image itself, so the memory i ask him to read was not found into the memory of the object. Simply, the error raises when i moved the starship that was already out of the screen and into the screen, so ask him to copy a background non existent.

I replace my code with:

    Bitmap bgpart = null;
    try 
    {
        bgpart = Primary.BackGround.Clone(rect, Primary.BackGround.PixelFormat);
    } 
    catch(Exception e)
    {
        bgpart = Primary.BackGround.Clone(new Rectangle(0, 0, b.Width, b.Height), Primary.BackGround.PixelFormat);
    }

So actually i sent him to read a surely existing part, and problem solved. In my case its ok because i try to read an non existent image part to draw it outside the screen - not needed anyways.

So these errors are (also) thrown from system.drawing when it is forced to read memory not supposed to. If it is safe to bypass, that depends on usage of that readings.

In my case it was safe because i was trying to read and write non existent image parts.


I'll tell you how I solved the problem. Use windows os

  1. Open the Print & Scanner window.

  2. Uncheck the box labeled Allow Windows to manage my default printer.

  3. Set the printer you want to use as the default printer.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜