Consider the following:
[Fact]
public void foo()
{
var result = new Subject<bool>();
var startCount = 0;
var completionCount = 0;
var obs = Observable
.Defer(() =>
{
++startCount;
return result.FirstAsync();
})
.Do(_ => ++completionCount)
.Publish()
.RefCount();
// pretend there are lots of subscribers at once
var s1 = obs.Subscribe();
var s2 = obs.Subscribe();
var s3 = obs.Subscribe();
// even so, we only expect to be started once
Assert.Equal(1, startCount);
Assert.Equal(0, completionCount);
// and we won't complete until the result ticks through
result.OnNext(true);
Assert.Equal(1, startCount);
Assert.Equal(1, completionCount);
s1.Dispose();
s2.Dispose();
s3.Dispose();
// now try exactly the same thing again
s1 = obs.Subscribe();
s2 = obs.Subscribe();
s3 = obs.Subscribe();
// startCount is 4 here instead of the expected 2!
Assert.Equal(2, startCount);
Assert.Equal(1, completionCount);
result.OnNext(true);
Assert.Equal(2, startCount);
Assert.Equal(2, completionCount);
s1.Dispose();
s2.Dispose();
s3.Dispose();
}
My understanding of Publish
+ RefCount
is that a connection to the source is maintained as long as there is at least one subscriber. Once the last subscriber disconnects, any future subscriber will re-initiate the connection to the source.
As you can see in my test, everything works perfectly the first time through. But the second time, the deferred observable inside the pipeline is executed once for every new subscriber.
I can see via the debugger that for the first group of subscribers, obs._count
(which counts subscribers) increases for each call to Subscribe
. But for the second group of subscribers, it remains zero.
Why is this happening and what can I do to rectify my pipeline?