C# 使用打开可观察流时正确订阅当前可观察流

C# 使用打开可观察流时正确订阅当前可观察流,c#,system.reactive,C#,System.reactive,我在使用System.Reactive时遇到了一些奇怪的情况。也许这是正常的行为,但对我来说没什么意义 让我们看一下下面的代码: Subject<IObservable<long>> X = new Subject<IObservable<long>>(); IObservable<long> I = Observable.Interval(TimeSpan.FromSeconds(1)); async Task Main() {

我在使用
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();
}
Subject X=新主题();
IObservable I=可观测的时间间隔(TimeSpan.FromSeconds(1));
异步任务Main()
{
Subscribe(X=>Console.WriteLine($“switched_1:{X}”);
I.Subscribe(x=>Console.WriteLine($“direct_1:{x}”);
Subscribe(X=>Console.WriteLine($“switched_2:{X}”);
I.Subscribe(x=>Console.WriteLine($“direct_2:{x}”);
等待Task.Factory.StartNew(异步()=>
{
等待任务。延迟(TimeSpan.FromSeconds(5))。配置等待(false);
订阅(X=>Console.WriteLine($“switched_3!!!:{X}”);
I.Subscribe(x=>Console.WriteLine($“direct_3:{x}”);
});
X.OnNext(可观察的时间间隔(时间跨度从秒(1))开始);
Console.ReadLine();
X.OnNext(可观察的时间间隔(时间跨度从秒(1))开始);
控制台写入线(“新的可观察发射”);
Console.ReadLine();
}
可观察到的标记为!!!在发出第二个间隔之前,不会命中

[更新]

我想我知道发生了什么:每次我都用一个新的开关订阅上游可观察对象。当我这样做的时候,我只会收到订阅后发出的可观察的通知,我不能“连接”到当前的可观察。 我认为只使用一次switch,并在以后订阅生成的observable将有助于:

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();
}
Subject X=新主题();
可观察席;
void Main()
{
席= x.Switch()
席(X= >控制台.Wrand Lead($“SwitcEd1:{x})));
席(X= >控制台.WrreLead($“SwitcEdE2:{x})));
X.OnNext(可观察的时间间隔(时间跨度从秒(1))开始);
席(X= >控制台.WrreLead($“SwitCheDe3,!!:{x})));
Console.ReadLine();
X.OnNext(可观察的时间间隔(时间跨度从秒(1))开始);
控制台写入线(“新的可观察发射”);
Console.ReadLine();
}
但没有:(

[更新2]

似乎我已经找到了一个实际可行的解决方案,但我不确定它是否被正确使用

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

IObservable<long> XI;

async Task Main()
{
    XI = X.Switch().Publish().AutoConnect();
...
Subject X=新主题();
可观察席;
异步任务Main()
{
席= x.Switch()
...

如何让它从一开始就工作?

您在[Update]下的解释是正确的,因为Task.Factory.StartNew返回的是一个任务而不是一个任务。您必须使用双waitTask。如果希望订阅在调用OnNext()之前发生,请运行

然而,只有像[Update2]中那样公开一个XI,并隐藏下面有一些东西被切换的事实,才是一个可行的选择


使用Publish().AutoConnect())您可以将可观察对象从冷转换为热。您还可以在代码片段中尝试一个行为主题或ReplaySubject,以了解热与冷之间的差异。如果您了解这些差异,您应该会更清楚,您心目中的实际解决方案应该是什么样子。

您在[Update]下的解释是正确的,因为Task.Factory.StartNew返回的是任务而不是任务。您必须使用双wait任务。如果希望在调用OnNext()之前进行订阅,请运行

然而,只有像[Update2]中那样公开一个XI,并隐藏下面有一些东西被切换的事实,才是一个可行的选择

使用Publish().AutoConnect()可以将可观察对象从冷转换为热。您还可以在代码段上尝试一个BehaviorSubject或ReplaySubject,以了解热与冷之间的差异。如果您了解这些差异,您应该会更清楚地了解您心目中的实际解决方案