2012-07-12 67 views
13

說我要來產生隨機數的異步流,其泵出新的價值每100毫秒。雖然試圖拿出一個解決方案,我第一次嘗試看起來是這樣的:Observable.Defer - 需要一些澄清,正是它

 var random = new Random(); 
     Observable.Start(() => random.Next()) 
        .Delay(TimeSpan.FromMilliseconds(100)) 
        .Repeat() 
        .Subscribe(Console.WriteLine); 

如果您嘗試並運行此,你會發現,它只是不斷一遍又一遍重複着同樣的價值。好吧,我想我誤解了重複如何工作。玩弄了一會兒後,我想出了這個和它的工作:

 var random = new Random(); 
     Observable.Defer(()=> Observable.Start(() => random.Next())) 
        .Delay(TimeSpan.FromMilliseconds(100)) 
        .Repeat() 
        .Subscribe(Console.WriteLine); 

所以我去MSDN文檔來了解什麼推遲其實就是做了,這是它說:

返回每當一個新的觀察員贊同調用可觀察到的工廠 可觀察序列。

我想我的困惑是:我的代碼示例中,我永遠只能訂閱可觀測一次,那麼爲什麼看似遍地調用Observable.Start(...)?或者我誤解Repeat()?任何澄清將是非常棒的。

回答

17

你誤會重複。基本上,Repeat每次完成後都會重新註冊一個可觀察對象。

Observable.Start顯然緩存值的你第一次調用訂閱,並在每次訂閱時段後返回它。這是第一個例子中一次又一次導致相同數字的原因。

推遲的工作是這樣的:

IObservable<T> Defer(Func<IObservable<T>> factory) 
{ 
    return Observable.Create<T>(obs => factory().Subscribe(obs)); 
} 

所以每次訂閱Defer觀察的時間,它必須調用factory功能。在這種情況下,工廠創建一個新觀察到,從而避免Start緩存行爲。

獲得您描述的序列的另一種方法是使用Interval來獲得您的計時並Select獲得隨機數。

Observable.Interval(TimeSpan.FromMilliseconds(100)) 
      .Select(i => random.Next()) 
      .Subscribe(Console.WriteLine); 
5

「生成」隨機數的一種簡單方法是使用.Generate。試試這個:

var rnd = new Random(); 

Observable 
    .Generate(
     0, 
     x => true, 
     x => x, 
     x => rnd.Next(), 
     x => TimeSpan.FromMilliseconds(100.0)) 
    .Subscribe(n => { });