使用可观察流上的开关时正确订阅当前可观察物

时间:2018-11-30 18:52:43

标签: c# system.reactive

使用System.Reactive时遇到了一些奇怪的事情。也许这是正常的行为,但对我来说意义不大。

让我们采用以下代码:

Subject<IObservable<long>> X = new Subject<IObservable<long>>();

IObservable<long> I = Observable.Interval(TimeSpan.FromSeconds(1));

async Task Main()
{

    X.Switch().Subscribe(x => Console.WriteLine($"switched_1: {x}"));
    I.Subscribe(x => Console.WriteLine($"direct_1: {x}"));
    X.Switch().Subscribe(x => Console.WriteLine($"switched_2: {x}"));
    I.Subscribe(x => Console.WriteLine($"direct_2: {x}"));

    await Task.Factory.StartNew(async () =>
    {
        await Task.Delay(TimeSpan.FromSeconds(5)).ConfigureAwait(false);
        X.Switch().Subscribe(x => Console.WriteLine($"switched_3 !!!: {x}"));
        I.Subscribe(x => Console.WriteLine($"direct_3: {x}"));
    });

    X.OnNext(Observable.Interval(TimeSpan.FromSeconds(1)));
    Console.ReadLine();
    X.OnNext(Observable.Interval(TimeSpan.FromSeconds(1)));
    Console.WriteLine("New observable emited");
    Console.ReadLine();
}

可观察到的标有!!!直到发出第二个间隔才被击中。

enter image description here

[更新]

我想我知道发生了什么:每次订购新开关时,我都在订阅上游的观察值。而且,在执行此操作时,我只会收到有关订阅后发出的可观察对象的通知,而我无法“连接”到当前可观察对象。 我以为只使用一次 switch ,以后订阅可观察的结果将有所帮助:

Subject<IObservable<long>> X = new Subject<IObservable<long>>();

IObservable<long> XI;

void Main()
{
    XI = X.Switch().AsObservable();

    XI.Subscribe(x => Console.WriteLine($"switched_1: {x}"));
    XI.Subscribe(x => Console.WriteLine($"switched_2: {x}"));

    X.OnNext(Observable.Interval(TimeSpan.FromSeconds(1)));
    XI.Subscribe(x => Console.WriteLine($"switched_3 !!!: {x}"));
    Console.ReadLine();
    X.OnNext(Observable.Interval(TimeSpan.FromSeconds(1)));
    Console.WriteLine("New observable emited");
    Console.ReadLine();
}

但不是:(

[更新2]

似乎我找到了一个切实可行的解决方案,但是我不确定该解决方案是否正确使用。

Subject<IObservable<long>> X = new Subject<IObservable<long>>();

IObservable<long> XI;

async Task Main()
{
    XI = X.Switch().Publish().AutoConnect();
...

如何从一开始就使它起作用?

1 个答案:

答案 0 :(得分:1)

您在[更新]下的解释是正确的,因为 Task.Factory.StartNew 返回的是Task 而不是Task。如果您希望订阅发生在调用OnNext()之前,则必须使用两次 await Task.Run

但是,仅像[Update2]中那样公开XI-Observable,并隐藏下面有切换的事实是可行的选择。

使用Publish()。AutoConnect()可以将可观察对象从冷转换为热。您还可以在代码段上尝试使用BehaviorSubject或ReplaySubject来了解冷热之间的区别。如果您了解这些差异,那么对您来说应该更加清楚,您实际想到的解决方案应该是什么样子。