10

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

IT researcher
  • 3,274
  • 17
  • 79
  • 143
  • what do you assign to Tooltip ? – Tigran Jul 18 '13 at 14:20
  • 1
    Can you show your code, please? Preferably some part that works with bitmaps? – Ry- Jul 18 '13 at 14:21
  • 1
    The only thing that's obvious is that you use ActiveX controls pretty heavily. Which can prevent the garbage collector from running often enough to keep you out of trouble. The kind of trouble you get when you don't use Dispose() on your System.Drawing objects. It bombs like this when you used up too many handles. – Hans Passant Jul 18 '13 at 15:00

2 Answers2

11

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.

Steven Doggart
  • 43,358
  • 8
  • 68
  • 105
  • 1
    During clicking on grid in my application Msflexgrid was not disposing.It was increasing gdi object for each click on grid and got solution.Then I solved the problem by running the program in debugger.Now the problem is solved and now gdi count stays at 250 to 300. Thank you a lot. – IT researcher Jul 19 '13 at 11:01
0

I don't say that this is THE answer, but it worked for me - eventually! I have clipart folders with jpg and other pictures in, of different sizes. I was putting together a vb.net app, using a datagridview, to display a picture gallery. It worked fine, for some folders, and failed for others, with the 'out of memory'. I looked for ages, and then checked what was actually IN the folders. I have an additional file INDEX.DAT, and once I coded to ignore this file - the problem vanished!