views:

665

answers:

3

Hello again,

I did nice winforms 2.0 application and it's working great and customers are still happy but unfortunatelly I cannot solve one issue. The problem is that after using app for a couple of hours, gdi user handles number is rising and rising and finally process cannot allocate more objects and app crashes...

I'm not doing anything fancy, it's regular app, a few forms, a few more modal forms, a few datagridviews and a lot tablelayoutpanels where I'm adding a lot labels and textboxes.

My questions are:

  • are there any "recommended-practises" concerning adding/removing regular system controls on forms at runtime (dgv/tlp)
  • how to detect system handles' leaks - preferably using visual studio and a kind of free plugin (profiler?)
+4  A: 

Detecting graphics and window handle leaks is very difficult. As to a particular strategy for finding them at runtime, I can't suggest anything (though I'd love to hear someone else's!).

As for preventing them, here are a couple of reminders:

  • While the Control class's finalizer will call Dispose(), this is non-deterministic. You are not guaranteed that ANY object will EVER get finalized by the garbage collector. It's likely that it will, but it's not a guarantee.
  • In keeping with the above, Forms are an exception. When a Form is shown in a NON-MODAL way (meaning through Show(), NOT ShowDialog()), then when the Form closes it will deterministically call Dispose(). Forms that are shown through ShowDialog() must have Dispose() called manually in order to deterministically clean up the control handle.
  • Keeping those two things in mind, the most important thing that you can do is to ensure that you always call Dispose() on any object that you explicitly create that implements IDisposable. This INCLUDES Forms, Controls, Graphics objects, even the graphics helper classes like Pen and Brush. All of those classes implement IDisposable, and all of them need to be disposed of as soon as you no longer need them.
  • Try to cache your graphics utility classes, assuming you're using some. While a Pen and a Brush are fairly lightweight to create, they do take up handles and need to be disposed of when you're finished. Rather than creating them all the time, create a cache manager that allows you to pass in the parameters that you would use in the constructor for those objects and keep that object around. Repeated calls with the same parameters should still only use one single instance. You can then flush your cache on a periodic basis or at specific places in your application if you know where those would be.

Following those guidelines will greatly reduce--if not eliminate--your handle leaks.

Adam Robinson
Thanks for your advices.Can you recommend me any tools/VS plugins which can help to trace/detect leaks in source code?
tomo
@tomo, Again, no, I don't know of any such tools. I did quite a bit of looking at one time because I was experiencing issues similar to those you are facing. Solving them is what led me to the tips above.
Adam Robinson
Forms that are part of an MDI app also need to have Dispose() called manually: The two conditions when a form is not disposed on Close is when (1) it is part of a multiple-document interface (MDI) application, and the form is not visible; and (2) you have displayed the form using ShowDialog. In these cases, you will need to call Dispose manually to mark all of the form's controls for garbage collection.
Eric J.
@Eric: Could you point to an authoritative link on this? I don't see any reference to this behavior on MSDN and I'm not familiar with it. The ShowDialog is correct (as I referenced in my answer), but I can't seem to find confirmation of the MDI behavior.
Adam Robinson
+1  A: 

I find that using the Task Manager with the GDI Objects column visible essential to finding such leaks. You can target specific areas by breaking before the call, make a note of the GDI objects, then break after the suspect call to determine if the objects are being released properly.

Lyndsey Ferguson
Yeah, I detected the issue using the taskmanager and the reason of askinmg this question is how to help to fix it.
tomo
In that case, I think Adam Robinson's post should help you fix the problem.
Lyndsey Ferguson
A: 

The source code for two useful GDI leak tracking tools can be found here: link text

I have used it successfully on many Visual Studio C++ projects. I am not sure whether I work with .NET as well.

fmunkert