In one of my VB.Net applications i am getting error while running the application. This error does not come always. So i am not able to reproduce the error also. No exact sequence also to reproduce the error.
Stack :System.OutOfMemoryException: Out of memory.
at System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)
at System.Windows.Forms.ToolStrip.OnPaint(PaintEventArgs e)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ToolStrip.WndProc(Message& m)
at System.Windows.Forms.StatusStrip.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Error description:
MyApplication_UnhandledException
After this error i get a message saying,
Insufficient memory to create bitmap. Close one or more applications to increase available.
When i checked the memory usage of the application it was not that high. This error does not appear repeatedly. So how i can troubleshoot this error. How can it be solved?
I checked running my application by using .Net memory profiler and redgate memory profiler.
Below is a screenshot of the amounts of unmanaged memory usage. I don't know properly whether these values are high.
UPDATE:
i got the error again.checked the gdi objects and it was 9998.So the error was due to high gdi objects.Now question is how to solve.Then i used GDIView and checked.By that tool i got pen-2954 brush-5918 font-90 bitmap-13 etc GDI total-9998
So what theses pen and brush are? In my code i don't have brush or pen used.(I searched the code for 'pen' and 'brush' but didnt't get any.) So please help me on this
In your Task Manager, go to the View menu to select which columns to show in the Processes tab. Select that you want to show the GDI Objects column. I'm fairly certain that you will see that the total GDI objects for your process is reaching 10000, which is the maximum for any process.
It is not a matter of how much physical memory is being used. In that sense, the error message is very poor and misleading. The problem is that you have run out of GDI handles. Each process under windows is limited to a maximum number of GDI handles that they can create. The limit is currently 10000 handles per process.
The reason I'm assuming that your problem is the GDI handles is because the exception is thrown when it's trying to create a new bitmap during the process of painting the control. A bitmap is a GDI object. Creating a bitmap uses up a GDI handle for that bitmap. Therefore, that is most likely the cause.
Since the error is happening in the standard ToolStrip
control, it's unlikely to be a bug with the ToolStrip
, itself. It's far more likely that you are, elsewhere in your program, using up all of the GDI handles, and then, when the control tries to paint itself, it fails because there are no handles left.
Any time you are creating GDI objects such as pens and bitmaps, you need to make sure that you dispose those objects. All of the GDI classes that acquire GDI handles implement the IDisposable
interface. When the objects are disposed, they automatically delete their handles at that point. But, if you never dispose of the objects, the handles never get deleted and your GDI-object count will just keep growing.
To dispose of any IDisposable
object, you can simply call the Dispose
method when you are done with the object, for instance:
Dim b As New Bitmap("test.bmp")
'...
b.Dispose()
However, if you can, it's even better to declare the variables for IDisposable
objects with a Using
block, like this:
Using b As New Bitmap("test.bmp")
'...
End Using
With the Using
block, the Dispose
method will be called automatically for you, so you don't need to explicitly call it yourself. The reason that the Using
block is better than calling Dispose
yourself is because, if an exception is thrown while inside the Using
block, the Dispose
method will still be called automatically. If you are calling it explicitly yourself, without a Using
block, it's easier to miss every place that you need to call it.
To find the problem area in your code, run your program in the debugger and step through your code. Leave the Task Manager open, showing the GDI Objects column, while you are stepping through your code. Watch the GDI Objects column in the Task Manager and you will see the count increase as new GDI objects are created. It should be fairly easy, using this method, to see where the problem is.