DelegateCommand Memory Leak

Topics: Prism v4 - Silverlight 4
Sep 27, 2011 at 4:22 PM

Issue 4065 describes a memory leak in the DelegateCommand whereby a DelegateCommand would retain a strong reference to CanExecuteHandled handler of the control that was binding to it.  This was resolved in Prism v2.1 with the introduction of the WeakEventReference class. 

However in Prism v4 the original behavior has been restored for Silverlight applications.  If Silverlight the WeakEventReference class is not used.  I was wondering why this older leaky functionality has been returned?

Regards Kaneda

Developer
Sep 27, 2011 at 9:33 PM

Hi,

Based on my understanding, the handling of week references inside the DelegateCommand  was changed to work correctly based on the way Silverlight 4 implements command hookup.

You can find this explained in more detail in Brian Noyes’ blog post, Command Changes in Prism 4:

“Until Silverlight 4, there were no built in command handlers, so this was really only relevant to WPF anyway. And WPF does things a little differently under the covers than the implementation that ended up in Silverlight 4. In WPF, in addition to holding a reference to the command object itself ( so that Execute and CanExecute can be called), the command source (i.e. Button) holds a reference to the delegate instance that exposed the CanExecuteChanged event (which would be something like your view model, as opposed to the command object itself). Silverlight 4 does not hold that additional reference.
So that required a small change that you might run across if you are looking at the code, where the DelegateCommand uses a weak reference wrapper to command source when you are in WPF and not in Silverlight. This is to accommodate this difference in the platforms. “

I hope you find this helpful.

Agustin Adami
http://blogs.southworks.net/aadami

Sep 28, 2011 at 11:10 AM
Edited Sep 28, 2011 at 11:12 AM

Hi Agustin

Thanks for the reply.  I understand from you response why it has been changed but this does mean that Silverlight is now prone to the same memory leak that WPF had and was fixed with 4065. 

When the Button is bound to the DelegateCommand it subscribes to the CanExecuteChanged event and it never unsubscribes.  This means that the DelegateCommand retains a reference to the Button thereby rooting it and preventing it from being GC'ed, causing a memory leak.  Issue 4065 fixed this for WPF by making the DelegateCommand hold a weak reference to the Button's CanExecuteChanged callback delegate.  However as Brian Noyes mentioned this won't work for Silverlight since unlike WPF a Silverlight button does not retain its own reference to the CanExecuteChanged callback delegate it provides.  Thus if WeakEventReferences were used in Silverlight it would result in nothing holding a reference to the callback delegate leaving it prone to being GC'ed at any time.  This is why Silverlight can't use WeakEventReferences however not using WeakEventReferences means we go back to having the same memory leak we had in the first place.

Anybody got any thoughts on this?

Regards

Kaneda