取消Observable订阅并等待Observer完成

时间:2017-08-13 22:59:13

标签: system.reactive

有没有更好的方法来编写下面的代码来实现帖子主题中所述的内容?

我发现以下代码过于复杂且过于繁琐而使用额外的Subject<long>,并且除非您在每个可观察对象中进行硬编码,否则不容易创建通用解决方案。

var subject = new Subject<long>();
var cts = new CancellationTokenSource();
var observable = Observable.Interval(TimeSpan.FromSeconds(2));
var disposable = observable.Do(l => {
    {
        Console.WriteLine($"Start {l}-{DateTime.Now}");
        Thread.Sleep(2000);

        Console.WriteLine($"Stop {l}-{DateTime.Now}");
        subject.OnNext(l);
    }
}).Subscribe();
cts.Token.Register(disposable.Dispose);

Thread.Sleep(5000);
subject.Subscribe();
cts.Cancel();
subject.FirstAsync().Wait();

Console.WriteLine("Finish");

2 个答案:

答案 0 :(得分:3)

您最好使用Subject<Unit>编写代码以表示完成。使用bool数组有点乱,可能会让你在多线程代码中使用这种技术感到悲伤。

试试这个:

var observable = Observable.Interval(TimeSpan.FromSeconds(2));
Subject<Unit> finish = new Subject<Unit>();
observable
    .TakeUntil(finish)
    .Do(l =>
    {
        Console.WriteLine($"Start {l}-{DateTime.Now}");
        Thread.Sleep(2000);
        Console.WriteLine($"Stop {l}-{DateTime.Now}");
    })
    .Finally(() => Console.WriteLine("Finally"))
    .Subscribe(
        l => Console.WriteLine("OnNext"),
        () => Console.WriteLine("Complete"));

Thread.Sleep(5000);
finish.OnNext(Unit.Default);
Console.ReadLine();

它产生:

Start 0-2017/08/15 13:37:03
Stop 0-2017/08/15 13:37:05
OnNext
Start 1-2017/08/15 13:37:05
Stop 1-2017/08/15 13:37:07
OnNext
Complete
Finally

答案 1 :(得分:0)

实际上取消订阅导致没有进一步的信令。正确的做法是等待完成。订阅在完成后自动处理,因此无需进一步处理

        var observable = Observable.Interval(TimeSpan.FromSeconds(2));
        bool[] finish = {false};
        observable.TakeWhile(l => !finish[0]).Do(l => {
            Console.WriteLine($"Start {l}-{DateTime.Now}");
            Thread.Sleep(2000);
            Console.WriteLine($"Stop {l}-{DateTime.Now}");

        }).Finally(() => Console.WriteLine("Finally")).Subscribe(l => {
            Console.WriteLine("OnNext");
        },() => Console.WriteLine("Complete") );
        finish[0] = true;
        Console.ReadKey(true);

以上产生相同的输出而没有额外的主题