Monday, 23 October 2006

Events in the .NET Framework implement the Observer design pattern. What this means is that under the hood when one object (Observer) wants to be notified about some event that occured in another object (Subject), it has to register one of its methods in a special list of methods stored in the Subject. In .NET those methods are really delegates. When an event occurs what really happens? The Subject iterates through the collection of the delegates it stores and invokes them one at a time. It is a simple overview of how it works. It is not meant to be a complete description. Just keep in mind the in fact it is the Subject who holds the referrence to the Observer and not the other way around.

So, given the introduction you know that Subject knows about all the registered Observers - it holds a referrence. Sometimes the Observer also holds a referrence to a subject such as in a Form handling a Click event of a contained Button control. In this situation there is in fact a circullar referrence between the objects!

What does this mean and why it is important? The problem starts to appear when you have an object A with an event E. If this object has a long life cycle then every event you hook up to this object will cause its defining Observer not to be garbage collected. Take for example a Windows Forms application when the A object is passed between number of forms - maybe a wizard-like procedure - and each step attaches its own handlers to the E event. Long after the windows are closed, the object still lives and by doing so, it prevents the Forms from being collected by the GC (via the referrence the Subject has to the Observers). And that is not all to it! Imagine for example that you have your first form closed via Close method (which should call Dispose to release the unmanaged resources). After a while the E event is rised and it will be handled inside the Form which sa been closed long time ago. If in the handler you will try to use the resources that have already been released - exception will be thrown!

So given the problem there is a simple solution. Just remember to unhook the event handlers from Subject when they are no longer needed. When that is? It depends. Only you can tell. The sad thing is that the necessity of manually removing the event handler from the event is something to REMEMBER which is not always that easy and certainly it is a source of MANY unexpected "memory leaks" in the applications.

kick it on