tags:

views:

62

answers:

1

I'm currently having some trouble with an MVVM WPF application. In the application, the ViewModel is associated as the DataContext for a View using a DataTemplate in a ResourceDictionary - this way neither object has an in-code reference to the other. My ViewModel has an unmanaged resource which needs to be released when my ViewModel is gone. (In this case, my resource is a class using an external DLL)

If I don't actually use the DLL, when I close the application, the finalizer for my unmanaged resource is called, which cleans up the DLL (I'm implementing IDisposable). Everything good there.

If I use the DLL, when I close the application, the finalizer for my resource is not called and the process doesn't end. If I break, I can see that the DLL is blocking on a call to System.Net.Sockets.Socket.Receive(). I'm assuming what's happening is that somehow my DLL is outliving my ViewModel, so the ViewModel is never being finalized.

From what I've read, it's bad design to rely on an object being finalized - you can't trust the GC. So, what options do I have to call CleanUp() on my resource when I want to close the appplication - given that the View and ViewModel don't have references to each other?

Edit: For some extra reading, this is the blog post about Finalizers I was referencing.

Edit 2: I came up with a solution that I'm reasonably happy with, so I figured I'd add it for posterity and pseudo-close this question. On App Startup I initialize the main View and ViewModel for my application, so it's the one source which has a reference to both. I attached an EventHandler on View.Closed which triggers a CleanUp() method on my ViewModel, which is able to propagate that logic throughout the application. I maintain MVVM and get to clean up offending resources without too much trouble.

+1  A: 

No, you can definitely trust the GC. You can't trust DLLs that you didn't write that start threads that call Socket.Receive(). You'll have to tackle this by talking to the owner of the DLL code. If you actually created the thread yourself then set its IsBackground property to true.

Hans Passant
I tried invoking the DLL call on a thread where I set IsBackground to true - but I still had the same issue. I was hoping if the UI Dispatcher had nothing else to do, it could coerce the other to stop.
bsg
+1 for setting IsBackground to true (if you own the thread). You *can* rely in the GC to finalize your object, but you *can't* rely on the GC to free references to objects for you. If your object has references to any other undisposed object (event handlers being a big one) then the GC will not delete your object. In essence, you can still have memory leaks with .NET and eat up all the available memory on your computer, just none that escape your AppDomain - so when your app shuts down you *can* trust the GC to free all memory associated with your app.
Doug