为什么/如何使用无连接发布?

时间:2018-12-12 16:28:48

标签: system.reactive rx.net

为什么/应该在没有.Publish()Connect呼叫的情况下使用RefCount?它有什么作用?示例代码:

var source = new Subject<int>();

var pairs = source.Publish(_source => _source
    .Skip(1)
    .Zip(_source, (newer, older) => (older, newer))
);

pairs.Subscribe(p => Console.WriteLine(p));

source.OnNext(1);
source.OnNext(2);
source.OnNext(3);
source.OnNext(4);

pairspairs2有何不同:

var pairs2 = source
    .Skip(1)
    .Zip(source, (newer, older) => (older, newer));

1 个答案:

答案 0 :(得分:0)

Publish<TSource, TResult>(Func<IObservable<TSource, IObservable<TResult>> selector)重载记录不充分。 Lee Campbell不在introtorx.com中进行介绍。它不会返回IConnectableObservable(大多数人都与Publish相关联),因此不需要或不支持ConnectRefCount通话。

Publish的这种形式基本上是一种防御性编码形式,可避免源中可观察到的副作用。它订阅源一次,然后可以通过传入的参数安全地“多播”所有消息。如果您查看问题代码,则只会提及一次source,而只有两次提及_source_source是安全多播的可观察对象,source是不安全的多播对象。

在上面的示例中,源是简单的Subject,因此它并不是真正不安全的,因此Publish无效。但是,如果要用以下内容替换source

var source = Observable.Create<int>(o =>
{
    Console.WriteLine("Print me once");
    o.OnNext(1);
    o.OnNext(2);
    o.OnNext(3);
    o.OnNext(4);
    return System.Reactive.Disposables.Disposable.Empty;
});

...您将发现pairs(正确)打印了一次“ Print me一次”,而pairs2打印了两次。在您的观察对象将诸如DB查询,Web请求,网络调用,文件读取以及您希望只发生一次而不是多次发生的其他副作用代码之类的东西包装起来的情况下,这种影响具有类似的含义。

TL; DR::如果您有一个引用了两次可观察对象的可观察查询,则最好将其包裹在Publish调用中。