2012-07-12 83 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 => { });