I use some UserControls
which get created and destroyed within my application during runtime (by creating and closing subwindows with these controls inside).
It
WPF doesn't support IDisposable
well. If you're implementing a WPF control that needs cleanup, you should think about hooking into the Loaded and Unloaded events instead (or in addition).
I.e. you connect to the event in the Loaded
handler and disconnect in the Unloaded
handler. Of course this is only an option if your control does not need to receive the event while it's not "loaded" and if you can correctly support many load/unload cycles.
The advantage of using the Loaded
/Unloaded
events is that you don't have to manually dispose the user control everywhere it's used. You should however be aware that the Unloaded
event is not fired after application shutdown has begun. E.g. if your shutdown mode is OnMainWindowClose
, the Unloaded
events for other windows will not be fired. This usually isn't a problem though. It just means that you cannot do stuff reliably in an Unloaded
that must happen before/while the application terminates.
Event handlers are tricky and can easily hide a resource leak. As Tigran says. Use IDisposeable and forget about destructors. I recommend measuring whether you got it right. Just by looking at the memory consumption of your app in task manager will tell if a leak is present if you stress test it a little bit by loading up and closing a few thousand windows.
The GC will take care of that. While the event holds a strong reference, it only holds it on the parent object itself. In the end only MyControl will keep a reference via the event handler, thus the GC will collect it.
On the otherhand using the finalizer, which is NOT a descrutor. Is for this bad practice. If you want to unregister an event, you should consider IDisposable
.
If the code got to the destructor, it doesn't matter anymore.
That's because it will only be destroyed if it isn't listening to any events anymore.
If it was still listening to events, it wouldn't have been destroyed.
There are some cases where unsubscribing from an event in a Finalizer/destructor could be useful, if the event publisher guaranteed that unsubscription was thread-safe. For an object to unsubscribe from its own events would be useless, but one could as a workable pattern have a public-facing object hold a reference to a private object that actually "does all the work", and have that private object subscribe to events. If there is no reference from the private object back to the public object, the public object will become eligible for finalization once nobody is still interested in it; its finalizer would then be able to cancel the subscription on behalf of the private object.
Unfortunately, this pattern can only work if the objects whose events are subscribed guarantees that it can accept unsubscription requests from any threading context, and not just the context where events were subscribed. Having .NET require as part of the "event" contract that all unsubscribe methods must be thread-safe would not have imposed a major burden on implementations, but for whatever reasons MS did not impose such a requirement. Consequently, even if a Finalizer/destructor discovers that an event should be unsubscribed as soon as possible, there is no standard mechanism by which it can make that happen.
2) This does work
1) I had a case ( with an In-App messaging service ) that event handlers to a global object where not released and the GC couldn't collect the object because of that. I think this is usually a rare condition - using a profiler like ANTS from red gate you could easily do a memory profiling if you think this happens to to you.