I have changed the DirtyObjectCatcher so that it initially only hooks
Form.Disposed – Automatically disposes the DirtyObjectCatcher
Form.Closed – Unhooks all additional form events (below)
Form.Shown – To hook additional form events (below)
==Additional form events==
The additional events are to ensure that the DirtyObjectCatcher’s undo block is moved to the top. The reason that these events are now unhooked is so that there is no strong event references from the application’s main form (Form.MdiParent) to this component, keeping it alive. Now we only have long-term event references from the owning form itself. Really though this is just an added precaution against something I may not have thought of 🙂
The true memory saver comes from only holding a WeakReference to the owning form. Otherwise in an MDI application we have the following
In such a case closing the MDI child form will not be collected it because it is referenced by the DirtyObjectCatcher, which cannot be collected because it is referenced by the application’s main form. Unhooking these events and holding only a WeakReference prevents the leakage.
In addition I have hooked Form.Disposed so that this component is disposed along with its owner. I have also hooked DirtyObjectCatcher.Disposed from ObjectValidator so that it may also auto-dispose itself and knows not to place any new subscriptions.
Again the files are available here.
In addition I was able to track down and reproduce a couple of leaks in ECO 4 which are now fixed internally.
- Deactivating / Reactivating an EcoSpace would leak an object reference each time. This is not the case if you allow the EcoSpace to be collected.
- Using OclVariables with OclPsHandle and calling EcoSpace.Persistence.Refresh would leak a single object reference, also if OclPsHandle.Execute was executed.
I monitored my app with over 4,000 tasks today (normally there are about 200) for a few hours and the memory usage didn’t budge!