2
votes

I have a main window we'll call main and a child window we'll call child with a user control in the child we'll call control.

Program starts with main and the user performs some action to launch child which has control which has a FileSystemWatcher among other things. However, I started noticing that the FileSystemWatcher events are still firing after child has been closed. Uh oh. So I start digging...

When I subscribe to the Window_Closing event for child it triggers as expected. When I subscribe to the UserControl_Unloaded event for control it triggers as expected (immediately after child closes). So I put a destructor on control, which apparently is not happening until main is closed.

So why is the destructor for my user control not disposing the properties when the user control is unloaded? I would include code snippets if I knew which ones were pertinent...

2
How and where exactly are you disposing that FileSystemWatcher? Are you setting a field to null, or are you properly calling Dispose on it? - Pieter Witvoet
@Pieter I'm just setting it to null when the UserControl_Unloaded event triggers. - UndeadBob

2 Answers

0
votes

Well, after typing the question, the awesomeness of StackOverflow showed me this question which had a decent generic answer.

My solution was to unsubscribe all the FileSystemWatcher events in the UserControl_Unloaded event. Simply setting the watcher object to null was not sufficient. Seems like that's too much work for a managed language like .NET, but I guess not.

0
votes

FileSystemWatcher implements IDisposable. That normally indicates that a class uses unmanaged resources (such as file handles or unmanaged memory) that cannot be automatically (or timely) reclaimed by the garbage collector. IDisposable offers a Dispose method that such classes can use to properly release their unmanaged resources. Of course, cleanup could be done by other methods as well, but the IDisposable 'convention' makes it much easier for programmers to see which classes need cleanup. This also means that the word 'dispose' has a very specific meaning in C#.

It looks like a FileSystemWatcher remains alive if it's not disposed. Because you didn't remove those event handlers, it still contains references to your user control, so that remains alive as well, and you continue to see events being raised. Removing event handlers is a good idea (especially when the event-raising object has a longer lifespan), but in this case it only solves the symptom, not the underlying problem: it allows your user control to be reclaimed by the garbage collector, but the FileSystemWatcher is still alive.

As for destructors (they're normally called finalizers in C#), those are rarely needed. They can be used as a last resort by classes that implement IDisposable - just in case a programmer forgot to call Dispose - but there's a little cost to them (finalizers need to be registered in a queue and they're called by a special finalizer thread) and you can't control when exactly they are executed.