9

I'm creating a lot of custom controls and adding them to a FlowLayoutPanel. There is also a ContextMenuStrip created and populated at design time.

Every time a control is added to the panel it has its ContextMenuStrip property assigned to this menu, so that all controls "share" the same menu. But I noticed when the controls are removed from the panel and disposed of, the memory in use in Task Manager doesn't drop. It rises around 50kB every time a control is created and added to the layout panel.

I downloaded the trial of .NET Memory Profiler and it showed there were references to the menu strip hanging around after the controls were disposed. I changed the code to explicitly set the ContextMenuStrip property to null before disposing of the control, and yep, the memory is now released. Why is this? Shouldn't the GC clean up this type of thing?

H H
  • 263,252
  • 30
  • 330
  • 514
Dave
  • 113
  • 1
  • 6

2 Answers2

7

If you take a look at the ContexmenuStrip property of Control, you will see that the setter subscribes the control to the Disposed event of the MenuStrip, creating a back-reference from the MenuStrip to the Control.

This means it is a classic case of reachable-through-event and you already found the solution: set the ContexmenuStrip property to null.

H H
  • 263,252
  • 30
  • 330
  • 514
  • Thanks Henk. I'm new to c# but get the gist of what you mean. But why so much memory being taken up? After discovering this leak I realised that I wasn't unsubscribing from some custom events in my own classes before destroying the instances. And yet that didn't seem to be causing any increased memory consumption. Or is that a different beast? – Dave May 08 '10 at 20:53
  • 1
    Note that it's asymmetrical, if you had Disposed the ContextMenu there wouldn't be a problem. I would consider this a probable design fault of the ContextMenuStrip, it's sneaky to back-link like this. Beware of that in your own classes. But a when subscribing class is Disposed there is no problem. – H H May 08 '10 at 22:59
  • Oh ok. Thanks. I take it this is a rare problem in the .net framework then? Without the use of a memory profiler I probably wouldn't have picked up on this little devil. – Dave May 09 '10 at 00:15
  • Yes, fortunately it is rare. But you'll just have to keep an eye open for this, especially when WinForms controls are 'linked' like this. – H H May 09 '10 at 10:29
0

You should always dispose ContextMenuStrip in case you create it every time dynamical. This is because every time is a native handle created, but not destroyed. This means if you create contextmenu and show it, then close it and show it again you will run out of handles.

Trivalik
  • 80
  • 7