一般来说,没有定义任意可观察序列的订阅者计数的概念。
对于像Observable.Interval 这样的冷可观察对象,每次订阅可观察对象时,都会创建一个新的管道实例,从它的角度来看,它一次只能看到一个观察者。
尽管如此,我们可以预热一个寒冷的 observable,然后观察订阅的来来去去。
public static IObservable<T> RefCount<T>(this IObservable<T> source, Action<int> onChange)
{
var subscribers = 0;
var shared = source.Publish().RefCount();
void callback(int count) => onChange(Interlocked.Add(ref subscribers, count));
return Observable.Create<T>(observer =>
{
callback(+1);
var subscription = shared.Subscribe(observer);
var dispose = Disposable.Create(() => callback(-1));
return new CompositeDisposable(subscription, dispose);
});
}
演示
var values =
Observable
.Interval(TimeSpan.FromSeconds(0.1))
.RefCount(count => Console.WriteLine($"Subscribers: {count}"));
values.Take(5).Subscribe();
values.Take(10).Subscribe();
values.Take(15).Subscribe();
输出
Subscribers: 1
Subscribers: 2
Subscribers: 3
Subscribers: 2
Subscribers: 1
Subscribers: 0
现在,这行得通,因为我们拥有父 observable 的共享视图。
所以尽量让所有订阅都指向同一个实例。
_articles = GetArticles().RefCount(count => Console.WriteLine($"Subscribers: {count}")));
...
_articles.Subscribe();