C# 为什么在所有初始订阅服务器断开连接后RefCount不工作?

C# 为什么在所有初始订阅服务器断开连接后RefCount不工作?,c#,.net,system.reactive,C#,.net,System.reactive,考虑以下几点: [Fact] public void foo() { var result = new Subject<bool>(); var startCount = 0; var completionCount = 0; var obs = Observable .Defer(() => { ++startCount; return re

考虑以下几点:

[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();
}
[事实]
公共图书馆
{
var result=新主题();
var startCount=0;
var completionCount=0;
var obs=可观测
.延迟(()=>
{
++startCount;
返回结果。FirstAsync();
})
.Do(=>++completionCount)
.Publish()
.RefCount();
//假设同时有很多订户
var s1=obs.Subscribe();
var s2=obs.Subscribe();
var s3=obs.Subscribe();
//即便如此,我们也只希望启动一次
Assert.Equal(1,startCount);
Assert.Equal(0,completionCount);
//直到结果通过我们才能完成
result.OnNext(true);
Assert.Equal(1,startCount);
Assert.Equal(1,completionCount);
s1.Dispose();
s2.Dispose();
s3.Dispose();
//现在再试试同样的方法
s1=obs.Subscribe();
s2=obs.Subscribe();
s3=obs.Subscribe();
//这里的startCount是4,而不是预期的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();
}
我对
Publish
+
RefCount
的理解是,只要至少有一个订户,就可以保持与源的连接。一旦最后一个订户断开连接,任何未来的订户都将重新启动到源的连接

正如你在我的测试中所看到的,在第一次测试中,一切都很完美。但第二次,管道内的延迟可观测值对每个新订户执行一次

我可以通过调试器看到,对于第一组订阅者,
obs.\u count
(对订阅者计数)在每次调用
Subscribe
时都会增加。但对于第二组用户,它仍然是零


为什么会发生这种情况?我可以做些什么来纠正我的管道?

这是因为潜在的可观察结果已经完成。因此,每个新的订阅者只是得到未完成的回调

如果ObservableFer每次都在创建一个新的序列或一个没有完成的序列,那么您将看到所需的行为

e、 g

返回result.FirstAsync().Concat(Observable.Never());

您需要删除
Assert.Equal(1,completionCount)

来自@user631090的答案很接近,但不正确,所以我想我应该自己回答

这是因为
Publish
如果发布的流本身已经完成,那么它将立即完成新订户。您可以在图中看到:

但是,如果在底层流完成后,图中包含一个订户,那就太好了

更令人困惑的是,
Defer
仍然会为新订户调用。但是它的返回值被
Publish
忽略,因为初始流已完成


我还不能想出一种方法来实现我的预期用例。我想也许是使用
多播
而不是
发布
,必要时创建一个新主题。但我还没能做到这一点。对于我认为是一个常见的用例来说,这似乎相当痛苦。

这听起来似乎有道理,但我很难生成一个能按预期工作的序列。我原以为
返回结果。取(1)而不是
返回结果。FirstAsync()
本可以工作,但我得到了相同的结果。很奇怪。,
结果
尚未完成。勾选新值时,对
result.FirstAsync
的每个单独调用都将完成。我应该说result.FirstAsync已完成。我同意这种行为很奇怪。它看起来像是以某种方式被捕获的,因此未来的订阅者可以获得完整的可观测数据。您可以通过将第二组订阅者连接到已完成的事件上看到这一点,它们会立即启动,而不是等待您发送另一个.OnNext。因此,每个新订户都会增加计数。
result.FirstAsync
也未完成。即使我在
Defer
处理程序中创建了一个全新的
Subject
,我也会得到相同的行为。因此,它更像是正确地调用了
Defer
,以获取下一个可观察对象,但随后它被忽略了。可能是
Publish
/
RefCount
的bug?肯特,你介意(在另一篇文章中)解释一下你的预期用例吗?也许社区可以更直接地帮助你。(可能会减少活动部件的数量:主题+延迟+第一次+发布+引用计数,并给出问题(不是bug)可能会让我们提供更多帮助。当然,李。我刚刚发布了这个问题作为后续:
return result.FirstAsync().Concat(Observable.Never<bool>());