2017-08-13 158 views
2

有没有更好的方式来编写下面的代码以实现post主题中陈述的内容?取消可观察订阅并等待观察者完成

我发现下面的代码太复杂,太繁琐了,使用额外Subject<long>,并且不容易创建一个通用的解决方案,除非您在每个observable中进行硬编码。

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"); 

回答

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 
+0

我完全同意,我已经发现它我自己,但你应得的给予好评 –

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); 

完成后,认购自动处理上面产生相同的输出,无需额外的主题