ReactiveUI ObservableForProperty Life Cycle

I am curious about the lifetime of ObservableForProperty when I explicitly do not call Dispose on an Observer. I don't care in this scenario about getting subscriptions too long, etc.

In traditional .NET, if you have events, if you have not canceled your subscription, this could potentially lead to a memory leak due to the fact that your object lifetime is associated with the event. for example, as suggested at http://msdn.microsoft.com/en-us/magazine/cc163316.aspx :

Events can also be strong root links, and as such can contribute to a strong reference path and, thus, affect the lifetime of an object. Common events in the CLR 2.0 environment are bidirectional strong links between the event source and the listener and, as such, may contain an object (source or listener) that otherwise should already be dead.

Looking through the ReactiveUI code base when an INotifyPropertyChanged object is detected, I notice that you are using FromEventPattern subscribing to the INotifyPropertyChange event.

Does ObservableForProperty use this problem of keeping the object longer, creating a strong reference path?

Thanks Glenn

+8
garbage-collection c # system.reactive reactiveui
source share
1 answer

You are correct, using the WhenAny / ObservableForProperty method incorrectly can lead to a memory leak in your application if you are not careful. Consider the following code:

public ItemInAListBoxViewModel(MainWindowViewModel mainWindow) { this.window = mainWindow; // Reset the "selected" when the user minimizes this.WhenAnyValue(x => x.window.IsMinimized) .Where(x => x == true) .Subscribe(x => this.IsSelected = false); } 

Since we have WhenAny'd through an object whose life time is longer than ours (i.e. the ListBox vs Window element), we keep the ListBox elements forever until the window disappears (which may never be in your application).

You will avoid the vast majority of these cases, if only your character should be only when on your own object (i.e. always this.WhenAny , never someObject.WhenAny ).

Special Note on Dependency Properties

No matter what you have , to get rid of any WhenAny that passes through DependencyProperty, otherwise you will miss. Because Windows.

Crap, what should I do now?

A new feature has been added to ReactiveUI to handle the script in which you want to do this, but called "Activation". You can find additional information at:

Now we can define the area of β€‹β€‹β€œthings that should be active only when the screen is on” that will disappear immediately after the View and its ViewModel are removed from the screen (i.e. removed from the visual tree in WPF).

 public ItemInAListBoxViewModel(MainWindowViewModel mainWindow) { this.window = mainWindow; Activator = new ViewModelActivator(); // This gets called every time the View for this VM gets put on screen this.WhenActivated(d => { // The 'd' is for "Dispose this when you're Deactivated" d(this.WhenAnyValue(x => x.window.IsMinimized) .Where(x => x == true) .Subscribe(x => this.IsSelected = false)); }); } 

For this to work, here is what must be true:

  • Your VieWModel should implement ISupportsActivation (super easy)
  • The view associated with your ViewModel should also call WhenActivated .

That sounds super complicated!

It looks like this, but it is not at all. Just remember two things:

  • Do not WhenAny through objects that stick out forever, unless you also stick forever
  • If you need to use WhenActivated.
+18
source share

All Articles