Why is Observable.Finally not called when Observable.Generate finishes?

c#, system.reactive, task-parallel-library

Solution

Look at the return type of the `Finally` method; should give you a hint. Just like the `Concat` method returns a new `IObservable` with the new sequence concatenated to it, but doesn't change the original, the `Finally` method returns a new `IObservable` that has that final action, but you're subscribing to the original `IObservable`. Put the following line in front of your `Subscribe` call and it'll work.

o = o.Finally(() => "finallY".Dump());

I agree it's an odd API choice though; I'd think of `Finally` as being more akin to `Subscribe` than to `Concat`. You're subscribing to the finally "event"; it's odd that the API forces you to create a completely new IObservable and then subscribe to that just to get the `Finally` thing to happen. Plus it allows a potential error (made evident if we use the function in your question) that if you subscribe twice to that new IObservable, your `Finally` function will execute twice. So you have to make sure that one of your subscriptions is on the "finallied" IObservable and the others are all on the original. Just seems unusual.

I guess the way to think about it is that `Finally` isn't meant to modify the observable, but rather to modify the subscription itself. i.e., they don't expect you typically to make openly-accessible named observables that have `Finally` things (`var o = Observable.[...].Finally(...);`) rather it's meant to go inline with the subscription call itself (`var subscription = o.Finally(...).Subscribe(...);`)

Problem

I needed to alternate between two states with each state having a different interval time. The best way I could think of doing this was to use Reactive Extensions' Observable.Generate which is pretty awsome. From what I read on msdn and other sites, Observable.Finally() should fire if the observable "terminates gracefully or exceptionally". I was testing the following code (in LINQPad) to see how it works, but I can not get .Finall() to fire at all. ``` var ia = TimeSpan.FromSeconds(1); var ib = TimeSpan.FromSeconds(.2); var start = DateTime.UtcNow; var ct = new CancellationTokenSource(); var o = Observable.Generate( true, // s => !ct.IsCancellationRequested, s => (DateTime.UtcNow-start) < TimeSpan.FromSeconds(3) && !ct.IsCancellationRequested, s => !s, s => s ? "on" : "off", s => s? ib : ia) // .TakeUntil(start+TimeSpan.FromSeconds(3)) .Concat(Observable.Return("end")); o.Subscribe( s=> s.Dump(), ct.Token); var t = o.ToTask(ct.Token); t.ContinueWith(x => x.Dump("done")); o.Finally(() => "finallY".Dump()); // never gets called? Thread.Sleep(10000); ct.Cancel(); ``` If I make Thread.Sleep 10s, the observable sequence finishes and the Task.ContinueWith fires, but not .Finally(). If I make Thread.Sleep 2s, the observable sequence is canceled and the Task.ContinueWith again fires, but not .Finally(). Why not?

Original source