When you’re in school you learn that the .NET framework takes care of all that nasty memory management. From the moment you’re past all those small exercises and develop “real” software you quickly see that if you don’t follow some guidelines the garbage collector fails to reclaim memory.
The past week I’ve spent quite some time using ANTS Memory Profiler to look for leaks in a big project at work. It’s a Windows forms application which talks to online webservices. It was pretty clear from the start that any form that was opened remained in memory since the total memory footprint increased and never dropped. Using ANTS you can easily see how much instances of which class are active, how they are related and how much space they occupy. Rather fast I found that a lot of eventhandlers were keeping hold of the forms or presenters (we use MVC to create our UI) hence the memory footprint.
It’s a good practice that whenever you subscribe to an event, you also unsubscribe when you no longer need to know about it. Every += needs its -=. In some places its easy to spot. When you got one presenter, let’s see an OrderPresenter with one view, OrdersView, you quickly see the mistake that was made. But in more complex situations, let’s say that OrdersPresenter was also talking to an CustomerPresenter and OrderDetailPresenter which in turn talked to other presenters you’ll be switching between Visual Studio and ANTS to try to understand what’s going on in the system.
Never the less, I was able to get all the forms disposed properly when they were closed or no longer needed. Except in one specific situation. The application has a multiple document interface (MDI). When it starts it loads the OrdersOverview form and shows some global information, in this example all current orders. When I closed this overview screen and looked at the output from Ants the form was still in memory. No matter what I tried, for some reason the MDI parent kept referring to the MDI child which was closed. After hours of walking through the code to find the culprit I launched one Google query which found a page on Microsoft Connect. It’s a bug in the .NET framework, sigh, what a waste of time.
Another thing that was new to me was that whenever you show a form as modal and you close it. It will be kept active as well, you need to explicitly call Dispose to get rid of it. Four years of WinForm development and I still learn so much new stuff.