2008-06-27

DirtyObjectCatcher

Oh boy, what a nightmare! After days of messing around I finally found where the memory leak is in my app, it was in DirtyObjectCatcher!

The DirtyObjectCatcher used to subscribe to the DirtyListService, so that it was notified whenever an object was made dirty. I experienced this problem...

01: User creates a "Call" to a customer site.
02: User edits a purchase order.
03: Save purchase order (merges the undo block to the Call undo block and closes the form)
04: Edit the purchase order again from the Call form

The PurchaseOrder is already dirty so it wont get triggered again, this used to result in no constraints being checked etc and the possibility of entering dodgy data. The solution at the time was to have a static list in DirtyObjectCatcher

private List Instances;

whenever a new instance was created it would be added, whenever Dispose was called it would be removed. I then hooked into the cache chain and whenever a value changed I would call a static method on DirtyObjectCatcher which iterated over Instances and told each to check if anything had changed. It worked fine enough, and I put in a request to add a Subscribe method to IUndoBlock.

My request for IUndoBlock.Subscribe was soon added so I changed the code. Now it worked lovely! Unfortunately there was a problem! I had left the static code in the component just in case anyone was using it, I should really have just removed it as it is now obsolete. The really big problem however was that I had never added a Finalizer to the DirtyObjectCatcher class to call Dispose(). I had assumed the following in the Windows.Form default code template would call Dispose.



private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}



However I was wrong. The components on the form are never added to this "components" member. As a result the Instances list grew and grew, and was never emptied. DirtyObjectCatcher holds a reference to the EcoSpace, so this is why the memory usage got bigger and bigger! I was going to add the Finalizer and remove the instance from Instances, but I have decided to remove Instances completely!

Update: There were some other odd issues too which I will blog about tomorrow after I have released an update!

No comments: