subject.Dispose() vs subject.OnCompleted()

1.4k views Asked by At

What's the difference between .Dispose() and .OnCompleted() call on a Subject ?

Usually i dispose subscription to stop listening an observable and complete a subject when it's no longer useful anywhere on the code,

3

There are 3 answers

0
Theodor Zoulias On BEST ANSWER

According to the documentation of the Subject<T>.Dispose method:

Releases all resources used by the current instance of the Subject<T> class and unsubscribe all observers.

It seems that attempting to do anything with a Subject after disposing it, results to an ObjectDisposedException. You can't Subscribe to a disposed Subject for example. Any subscriptions that are active at the time the Subject is disposed, will be disposed too, and the unsubscribed observers will not receive OnCompleted notifications.

On the contrary a subject that has been completed by calling its OnCompleted method can still be subscribed at any time, in which case the subscribed observer will receive instantly an OnCompleted notification. Of course if the completed subject is one of the buffered types like the ReplaySubject, then the observers will receive a number of OnNext notifications before the final OnCompleted.

Personally I would consider calling Dispose to a ReplaySubject that is about to be discarded, in order to accelerate the recovery of the RAM used by its internal buffer. I am not sure if this would make any difference though, since the Dispose is generally supposed to release unmanaged resources, and the memory used by the buffer is most probably managed.

11
Enigmativity On

There is a very important semantic difference between calling .Dispose() and .OnCompleted() on a subject.

Consider this code:

Subject<int> subject = new Subject<int>();

IObservable<int[]> query = subject.ToArray();

IDisposable subscription =
    query
        .Subscribe(xs => Console.WriteLine(String.Concat(xs)));

subject.OnNext(1);
subject.OnNext(2);

If I then call subject.OnCompleted() I get 12 written to the Console. If, however, I call subject.Dispose() then nothing gets printed.

Some operators, like .ToArray() in my example code, expect the .OnCompleted() call to produce any value.

It is important to understand what queries you are performing on the subject to know how to end it properly - there are situations where both ways are valid.

I feel, though, that you are doing the right things with disposing of subscriptions and completing subjects.

2
Joel Coehoorn On

Usually i dispose subscription to stop listening an observable and complete a subject when it's no longer usefull[sic] anywhere on the code

I think you have those backwards. I'm not familiar with rx.net, but I do know the IDisposable and Observable patterns. IDisposable is used to release resources from an object when you are completely done with it and it's no longer useful. OnCompleted is for when you are done observing (the provider has finished sending notifications), even if the object might still have other uses.