shyam_
shyam_

Reputation: 2470

.Net Winform Controls (MenuItem, ToolBarButon, ContextMenu, Splitter etc ) not releasing my User Control. A Memory leak issue

I have a C# WinForm User control made up of many child user controls such as MenuItem, ToolbarButton, ContextMenu, Splitter, Panel..etc..I open and close this user control many times in a ActiveX container. I see its it leaks memory every time it is open and close. I called GC.Collect in the dispose of this control and found that it leaks less memory now. but still it leaks.

I have also called the dispose on all other child controls MenuItem, ToolbarButton, ContextMenu, Splitter, Panel..etc in Dispose method of User Control but still i see that my User control is not GCed.

Please find the image from .Net profiler..you can copy the link of image in other tab of browser to see it large aaTrendControl is the name of my user control.

enter image description here

Find the image when I click on one child control instance in enter image description here

Why MenuItem and ToolbarButton control are not releasing my UserControl even when I Dispose them..Is anything I am missing.

Upvotes: 1

Views: 445

Answers (1)

Louis Somers
Louis Somers

Reputation: 2964

Simply calling GC.Collect will not release everything that went out of scope in one go. Garbage collection is allot more complicated. There is a concept of generations. Referring to objects that in turn refer to objects place them in different generations, and one call to GC.Collect will most likely only remove the last generations in one cycle. Calling it multiple times will also have little effect. If there's not much to do it may just ignore the call and return with "I'm done".

I recommend you read the excellent book Under the hood of .Net Memory Management. It's a freely downloadable PDF with allot of details on what's going on.

From your story, it is likely you are creating many "handles". Every control on a form has a so-called handle. These are native windows resources, that need to be "pinned" in order for windows to send messages to them (mouse-over, click etc...). Pinned objects are even more complicated because the GC cannot simply move them to another part of memory when defragmenting, so excessive allocation of controls can cause fragmentation problems. In the old days (before windows XP) there used to be a hard limit on the number of handles that a process would be allowed to allocate.

You may want to consider using GDI+ a little more to save out extra controls. For example, when creating excel-like grids, it is custom to draw the whole grid on one canvas, and only when the user clicks (or focuses) on a single cell, overlay it with a textbox or dropdown control in-place. Creating separate controls for each cell would have an enormous overhead, even on a modern computer.

It's good practice to re-use controls instead of disposing them and recreating them. Reusing controls will have a huge positive impact on performance. This because of the fact that visual controls require a context switch between your process and the OS in order to acquire a handle. Unfortunately I don't know of a good book on windows forms. I learned most of the details from my old Delphi 2 books, almost two decades ago. I might be outdated on some details, but the essential basic concepts in WinForms have not changed since then. Even when you work with .Net, an old book on the native Windows API's should help you get an idea on what's going on under the hood.

.Net will take care of the memory management saving you quite some headache, but fragmentation can cause problems, which can be overcome by reusing visual objects instead of disposing them. If you really need to call GC.Collect in your code, it usually implies you are doing something else wrong (exceptions exist though).

Upvotes: 1

Related Questions