I recently spent about 12 hours researching a memory leak on one of our largest winforms applications. By opening and closing the main client form, the application could easily grow over 200MB in a period of a few minutes. This resulted in very "odd" errors such as "Failed to load ImageList." and even though the application had thread level exception handling the core would crash and the user would get booted.The â€œlapsed listenerâ€ problem occurs when objects subscribe to events and subsequently fall out of scope. The problem is that the event subscriber doesnâ€™t get garbage collected because the event is still holding a reference to it inside of the eventâ€™s invocation list. The event subscriber is still considered reachable from the GCâ€™s point of view. As such, it doesnâ€™t get collected until the event goes out of scope (which is usually at application shutdown) which means that the event subscriber is effectively â€œleakedâ€.
After much profiling and research with the memory profiler (Awesome tool BTW, paid itself off in this instance!) I discovered a root reference to an event delegate subscribing to an application security object. Since this security object's lifetime extended across the whole life of the application, every client form (although Disposed) would never leave the heap. Thus all 80,000+ related objects would remain active in the heap waiting for a message from the security object.
After adding one line of code to unsubscribe from the event, everything would be cleanly released and application memory performance is perfect!
Moral? If you subscribe to any delegate/event, be cognoscente of the lifetime of the subscribed object, otherwise to be safe, unsubscribe to the event on closing or disposing.