How many times is Reactive Extensions supposed to evaluate its various operators?
I have the following test code:
var seconds = Observable
.Interval(TimeSpan.FromSeconds(5))
.Do(_ => Console.WriteLine("{0} Generated Data", DateTime.Now.ToLongTimeString()));
var split = seconds
.Do(_ => Console.WriteLine("{0} Split/Branch received Data", DateTime.Now.ToLongTimeString()));
var merged = seconds
.Merge(split)
.Do(_ => Console.WriteLine("{0} Received Merged data", DateTime.Now.ToLongTimeString()));
var pipeline = merged.Subscribe();
I expect this to write “Generated Data” once every five seconds. It then hands off that data to both the ‘split’ stream which writes “Split/Branch received Data”, and to the ‘merged’ stream which writes “Received Merged data”. Last, because the ‘merged’ stream is also receiving from the ‘split’ stream, it receives the data second time and writes “Received Merged data” a second time. (The order it writes some of them in is not particularly relevant)
But the output I am getting is this:
8:29:56 AM Generated Data
8:29:56 AM Generated Data
8:29:56 AM Split/Branch received Data
8:29:56 AM Received Merged data
8:29:56 AM Received Merged data
8:30:01 AM Generated Data
8:30:01 AM Generated Data
8:30:01 AM Split/Branch received Data
8:30:01 AM Received Merged data
8:30:01 AM Received Merged data
It is writing “Generaged Data” twice. To my understanding, The number of downstream observers that are subscribed to the “seconds” IObservable should not affect the number of times that “Generated Data” writes (which should be ONCE), but it does. Why?
NOTE I am using the stable release v1.0 SP1 of reactive extensions in a .Net Framework 3.5 environment.
Presumably, they choose that approach to allow each subscriber to get its values at the same interval from their initial subscription. Consider how your alternate Interval would work:
What you end up with is something like this:
In this case, the two observers have noticeably different results depending on whether or not there is any other observer already attached. As it is implemented,
Intervalgives the same experience to each subscriber regardless of order or past subscribers.All that said, you can “convert”
Intervalto the behavior you describe by adding.Publish().RefCount()when creating thesecondsobservable.