2017-08-13 165 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); 

完成後,認購自動處理上面產生相同的輸出,無需額外的主題