EventAggregator related Memory Leak

Jul 7, 2012 at 1:18 PM
Edited Jul 7, 2012 at 1:27 PM

My project is built with SL5, Prism 4.1 & MVVM.

The following code does leak memory, keeping the viewModel alive in memory after closing my View/VM in UI:

viewModel = _container.Resolve<IFileEvidenceSubViewModel>();

To resolve this issue, I tried the below which again does leak memory (keeping viewModel alive after closing my View/VM:

viewModel = new FileEvidenceSubViewModel(_container.Resolve<IRegionManager>(), _container.Resolve<IEventAggregator(), _container.Resolve<IUnityContainer>(), new ChildWindowLoader(_container.Resolve<IRegionManager>(), _container.Resolve<IEventAggregator(), _container.Resolve<IUnityContainer>()));

 

The following however does not leak memory:

viewModel = new FileEvidenceSubViewModel(_container.Resolve<IRegionManager>(), new EventAggregator(), _container.Resolve<IUnityContainer>(), new ChildWindowLoader(_container.Resolve<IRegionManager>(), new EventAggregator(), _container.Resolve<IUnityContainer>()));

 

I am not registering EventAggregator anywhere with my container (Unity) explicitly.

Also, to note, I am using View first approach elsewhere in my project, and my Views create ViewModels (throug constructor injection) and in these ViewModels, IEventAggregator is constructor injected implicitly. However, there, no memory leak occurs.

So, the following does not leak memory:

view = _container.Resolve<IFileEvidenceSubView>();
public FileEvidenceSubView(FileEvidenceSubViewModel viewModel)
{
     InitializeComponent();
     this.DataContext = viewModel;
     ....
}

 

I verified this behavior in other projects as well (to bypass error, if any, specific to my viewmodel) with the same result.

Thanks in advance,

Dharmesh

Developer
Jul 10, 2012 at 5:46 PM

Hi,

Based on my understanding, this behavior could be caused by a strong reference held to your view model class.

In my opinion a possible cause could be the way you are subscribing to the events rather than how you inject the EventAggregator in your view model.

Take into account that if you use a strong reference subscription (by setting the keepSubscriberReferenceAlive parameter of the Subscribe method to true), you will have to manually unsubscribe it to enable proper garbage collection of your subscribing object when it is no longer used.

Another thing to consider, is that as mentioned in this section of the Prism documentation:

Due to Silverlight's security model, the methods supplied to Subscribe must be publicly accessible methods if you want a weakly-held subscription (which is the default CompositePresentationEvent behavior). Because lambda expressions and anonymous delegates are generated as private classes and methods, these cannot be used in conjunction with weak subscriptions.

Regards,

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

Jul 11, 2012 at 5:04 AM

Thanks Agustin,

I am not using strong reference subscription. The gcroot output (from windbg) for the ViewModel that stays in memory looks like below:

image

 

Also, if I don't use EventAggregator at all in the called view model, the leak still happens.

Can you please look at the debug output above and tell me if something seems wrong to you...

Thanks,

Dharmesh

Developer
Jul 11, 2012 at 6:08 PM

Hi Dharmesh,

I find it strange that if you don't use the EventAggregator at all in the view model you are experiencing a memory leak. Based on my understanding, just injecting the EventAggregator in your view model wouldn't create a strong reference to the view model; what is more, the EventAggregator should only hold references to instances of the EventBase class (this can be seen in the code of the EventAggregator class of the Prism library).

By looking at the output of the CGRoot command you posted above, it seems like the view model is being referenced by a subscription to the LoadEntityEvent. If this subscription is not a strong reference subscription, it would be helpful if you could provide use with a repro-sample application isolating this problem so that we can check this in more detail.

Regards,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Jul 12, 2012 at 3:47 AM

Got it!

Yes, guys it was keepSubscriberReferenceAlive parameter that I had set to true. Regrets for giving wrong information earlier (so foolish of me to be so confident).

Thanks a lot Agustin and  Damian for your help. Prism rocks!!!

Thanks again,

Dharmesh