Task.ToObservable() disposing of IObservable
-
Wednesday, February 13, 2013 4:30 PM
Hi,
What's the correct pattern for disposing of a Task<T>.ToObservable() automatically once it completes?
e.g.
Service.SaveDraft(data) .ToObservable() .ObserveOn(this.SyncContextScheduler) .Subscribe(i => this.ViewModel.MapFromResult(i), ReportError)
I was adding the disposable to a VM scoped compositeDisposable, but that means every time I make a call I'm adding unneeded baggage to the VM.
So thinking perhaps if I didn't put an OnCompleted handler in, it probably automatically cleans up, but not 100% sure this is the case?
Dan
- Edited by Dan Harman Wednesday, February 13, 2013 4:34 PM
All Replies
-
Wednesday, February 13, 2013 10:12 PM
Hi Dan,
Rx operators, custom operators that use Observable.Create, observable classes that derive from ObservableBase<T> and all ToObservable conversions implement an "auto-detach" behavior, such that when OnError or OnCompleted are called, the subscription is automatically disposed. Disposing after that is basically a NOP.
You only need to hang on to the subscription if you may want to cancel the operation later, by disposing it; though keep in mind that Task<T> is hot and many asynchronous operations in general don't support cancellation, thus disposing of the subscription doesn't necessarily mean that the operation will be stopped, it might only mean that the results are ignored once the operation actually completes.
If you want to allow cancellation by hanging onto the subscription, but you don't want to hang onto the subscription longer than you have to, then simply remove the subscription in the onCompleted handler. (Edit: And the onError handler.)
For example:
var disposables = new CompositeDisposable(); ... var s = new SingleAssignmentDisposable(); disposables.Add(s); s.Disposable = Service.SaveDraft(data) .ToObservable(SyncContextScheduler) .Subscribe( ViewModel.MapFromResult, ex => { disposables.Remove(s); ReportError(ex); }, () => disposables.Remove(s));- Dave
- Edited by Dave Sexton Wednesday, February 13, 2013 10:14 PM Updated: onCompleted "and onError" handlers
- Marked As Answer by Dan Harman Thursday, February 14, 2013 10:06 AM
-
Wednesday, February 13, 2013 10:16 PM
Hi,
Actually, an even simpler way - and one that covers the possibility that OnError and OnCompleted aren't called due to cancellation - is to use the Finally operator.
var disposables = new CompositeDisposable(); ... var s = new SingleAssignmentDisposable(); disposables.Add(s); s.Disposable = Service.SaveDraft(data) .ToObservable(SyncContextScheduler) .Finally(() => disposables.Remove(s)) .Subscribe(ViewModel.MapFromResult, ReportError);- Dave
-
Thursday, February 14, 2013 10:06 AMThanks Dave - great answer.

