15

假设我想生成一个异步随机数流,每 100 毫秒抽出一个新值。在尝试提出解决方案时,我的第一次尝试看起来像这样:

        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 文档了解 Defer 实际在做什么,这就是它所说的:

返回一个可观察序列,每当有新观察者订阅时,该序列就会调用可观察工厂。

我想我的困惑是:在我的代码示例中,我只订阅了 Observable 一次,那么为什么它似乎Observable.Start(...)一遍又一遍地调用呢?还是我误会了Repeat()?任何澄清都会很棒。

4

2 回答 2

20

You are misunderstanding Repeat. Basically, Repeat will keep resubscribing to an observable every time it is completed.

Observable.Start apparently caches the value the first time you call Subscribe and is returning it each time you subscribe. This is what causes the same number over and over in the first example.

Defer works something like this:

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

so every time you subscribe to the Defer observable, it must call the factory function. In this case, the factory creates a new observable, thus avoiding the caching behavior of Start.

An alternate way to get the sequence you described is to use Interval to get your timing and Select to get the random numbers.

Observable.Interval(TimeSpan.FromMilliseconds(100))
          .Select(i => random.Next())
          .Subscribe(Console.WriteLine);
于 2012-07-12T19:06:39.363 回答
6

“生成”随机数的一种简单方法是使用.Generate. 尝试这个:

var rnd = new Random();

Observable
    .Generate(
        0,
        x => true,
        x => x,
        x => rnd.Next(),
        x => TimeSpan.FromMilliseconds(100.0))
    .Subscribe(n => { });
于 2012-07-13T09:46:08.050 回答