Sep 22, 2011

Some WPF Memory Leak Gotchas

Just a couple of insights I recently gleaned tracking down memory issues. I used the CLR Profiler and it worked well with snooping on heap allocation to find out what references were still being held onto and by what objects.

If you bind directly to objects, make sure they implement INotifyPropertyChanged

Microsoft details this "by design" feature here. Basically, due to the way property change notifications are wired up when the bound-to-object doesn't support the INotifyPropertyChanged interface directly, WPF can leak references to your objects. In my case, these were our POCOs from the entity model, but theoretically it could be anything you bind to (unless it is a OneTime binding, as stated in the KB article). Simply making sure these objects implement the interface properly will eliminate this problem entirely. This is especially important if you, as did I, use any of the ADO.NET POCO Generators supplied by Microsoft, as I don't think any of them generate entities that implement this interface by default. You'll have to dive into the T4 and modify it yourself (which isn’t hard — don’t be afraid of the T4!).

If you use MEF, don't forget to call ReleaseExport

This only really applies if you are manually creating objects via the GetExport or GetExportedValue series of methods on the CompositionContainer. Disposing of the objects after you're done with them isn't enough, because the container persists references to them internally. If you make sure to call ReleaseExport on them instead of Dispose, it'll do the disposing for you and it'll release them from its own internal collections, too. In my case, this was a bit tricky because I was mostly using GetExportedValue. There's no overload of ReleaseExport that takes the underlying value. ReleaseExport expects an object returned from the GetExport series (either an explicit Export object or a Lazy<T>). This meant I had to change over to using GetExport instead, which wasn't a problem really, but it also meant I had to keep track of exports I had created but not yet disposed of, as in many cases the disposal was user-initiated (closing documents in an MDI, for instance).

No comments:

Post a Comment