views:

2610

answers:

4

I'm maintaining a web application that has a memory leak.

Based on my investigation using Red Gate ANTS memory profiler I'm pretty sure that the memory leak is caused by event handlers in the business layer.

There's a collection that registers an event handler on each item that's added so that the collection can re-sort when the item's date is changed. It appears that this event handler is the culprit.

The business layer for this application is quite complicated, so keeping the collection and its items in memory drags a bunch of other objects with it.

I've implemented IDisposable on the collection and removed the event handlers in the Dispose method:

p.OnPunchDateChanged -= this.OnPunchDateChanged;

However, implementing IDisposable doesn't help since I can't wrap all the references to the collection in using or try/catch blocks. This collection is used by portions of the application that I don't have control over.

How can I clear these event handlers to resolve this memory leak?

+4  A: 

First off, just to prove the point, try logging the adding and removal of events to a simple text file. Then, check how many were added vs removed.

It sounds as if there is a bug somewhere in the business logic which is not unregistering the event in all circumstances.

Simon Hughes
+3  A: 

If you've "correctly" implemented IDisposable then the events will be unregistered when the object is destroyed via garbage collection (even if the Dispose() method is not explicitly called by consumers of your class).

Here are some references for you:

"Note that even when you provide explicit control by way of Dispose, you should provide implicit cleanup using the Finalize method. Finalize provides a backup to prevent resources from permanently leaking if the programmer fails to call Dispose."

Ken Browning
+1 the finalizer is called by the GC - if you cannot guaranteed object dispose via Dispose because of object scope, or not having access to all code, you *can* guarantee that the finalizer will be called if you implement it - most apparent area this occurs is when making .NET add-ins for other programs.
Adam
+2  A: 

Didn't see an accepted answer here so I'll post this for future visitors. I had this same problem and discovered the culprit to be event handlers via a memory profiler as you did. The answer is to use weak referencing to connect your event publisher and subscribers. Here's an example created by the Silverlight team and shared via this blog post:

http://blog.thekieners.com/2010/02/11/simple-weak-event-listener-for-silverlight/

The class can actually be found in its entirety at the bottom of the post, but the explanation is worth reading. Hope this helps!

Andrew
A: 

The Dispose method on the collection should be called directly by your code because the event holds a reference to the collection. Your collection will never be destroyed by garbage collector.

You should also change the behaviour of the Remove and Clean methods of the collection to detach the event handler from the removed items.

munissor