15

100ミリ秒ごとに新しい値を送り出す乱数の非同期ストリームを生成したいとします。解決策を考え出そうとしたとき、私の最初の試みは次のようになりました。

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

これを実行しようとすると、同じ値を何度も繰り返し続けることに気付くでしょう。OK、私はリピートがどのように機能するかを誤解したと思います。少し遊んだ後、私はこれを思いつきました、そしてそれはうまくいきました:

        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

あなたはリピートを誤解しています。基本的に、Repeatは、完了するたびにobservableに再サブスクライブし続けます。

Observable.Startは、Subscribeを最初に呼び出したときに値をキャッシュし、サブスクライブするたびに値を返すようです。これが、最初の例で同じ数を何度も引き起こす原因です。

Deferは次のように機能します。

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

したがって、observableをサブスクライブするたびにDefer、関数を呼び出す必要がありfactoryます。この場合、ファクトリは新しいobservableを作成するため、のキャッシュ動作を回避できStartます。

説明したシーケンスを取得する別の方法はInterval、タイミングSelectを取得し、乱数を取得するために使用することです。

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 に答える