Aaron Stainback
Aaron Stainback

Reputation: 3657

When to dispose of mouse events using Rx in WPF

Given the following code:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var mouseMove = Observable
            .FromEventPattern<MouseEventHandler, MouseEventArgs>(
            eventHandler => this.MouseMove += eventHandler,
            eventHandler => this.MouseMove -= eventHandler);

        var mouseMoveSubscription = mouseMove.Subscribe(args =>
        {
            //Do Something
        });
    }
}

Where is the correct\best place to dispose\unsubscribe from mouseMoveSubscription given I want the subscription to follow the MainWindow's lifetime. My main concern is I don't cause a memory leak that lasts past the windows lifetime. Thanks.

Upvotes: 2

Views: 492

Answers (3)

JerKimball
JerKimball

Reputation: 16904

I generally agree with @Honza that Closing is the appropriate place to do this - but I follow this pattern generally for "hosted" IDisposables; it might be a touch overkill in places, but I find it to be a lightweight-enough pattern that it is generally applicable:

// Window, application, etc - some longish-living object
public class Something : IDisposable
{
    CompositeDisposable _disposables = new CompositeDisposable();

    public Something()
    {
         // A composite disposable acts like a "bucket" of IDisposables
         // that are all disposed when the bucket is disposed.
          _disposables.Add(SomeObservable.Subscribe(...));
          _disposables.Add(SomeOtherObservable.Subscribe(...));
          _disposables.Add(YetAnotherObservable.Subscribe(...));

         // Here, optionally wire some "Yo, I should dispose when this happens" handler
         this.Closed += (o,e) => Dispose();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            // clean up managed resources here
            if(_disposables != null)
            {
                _disposables.Dispose();
            }
        }   
        // clean up unmanaged resources here
    }

    ~Something()
    {
        Dispose(false);
    }
}

Upvotes: 1

H_Andr
H_Andr

Reputation: 179

To do this in a more composable way with Rx, consider creating an Observable stream from the 'CloseEvent' the people above have already mentioned.

e.g. var closingObservable = Observable.FromEventPattern(this.Closing... etc) Then, amend your query to use TakeUntil: mouseMove.TakeUntil(closingObservable).Subscribe(args =>

You then needn't concern yourselve with explicit disposal.

Upvotes: 3

Honza Brestan
Honza Brestan

Reputation: 10947

I think the best place from the window lifetime point of view is the Closing event.

It is the beginning of the window's shutdown process (as shown here or here) - I find it better to unload everything as soon as I know it is to be unloaded (or unsubscribed in this case). If you need to keep subscribed as long as possible for any reason, use the Closed even instead.

Upvotes: 1

Related Questions