1

次のコンストラクターを持つ単一の Window WPF アプリケーションがあります。

        numbers = Observable.Generate(DateTime.Now,
                                         time => true,
                                         time => DateTime.Now,
                                         time => { return new     Random(DateTime.Now.Millisecond).NextDouble() * 99 + 2; },
                                         time => TimeSpan.FromSeconds(1.0));


        numbers.ObserveOnDispatcher()
            .Subscribe(s => list1.Items.Add(s.ToString("##.00")));

        numbers.Where(n => n < 10).ObserveOnDispatcher().
            Subscribe(s => list2.Items.Add(s.ToString("##.00")));

リストのスクリーンショットは次のとおりです。左側のリストに 3.76 がないことに注意してください... この動作は断続的です。

画像

4

1 に答える 1

7

短い答えは、あなたがそれを間違っているということです。Rx は完全に機能しています。

オブザーバブルを作成すると、時間の経過に伴う実際の値のシーケンスではなく、時間の経過に伴う値のシーケンスの定義が作成されます。これは、オブザーバブルへのサブスクライバーがあるときはいつでも、各サブスクライバーに対してオブザーバブルの新しいインスタンスを作成していることを意味します。

したがって、あなたの場合、このシーケンスの 2 つのインスタンスが動作しています。

var numbers =
    Observable
        .Generate(
            DateTime.Now,
            time => true,
            time => DateTime.Now,
            time => new Random(DateTime.Now.Millisecond)
                .NextDouble() * 99 + 2,
            time => TimeSpan.FromSeconds(1.0));

ここで、このオブザーバブルを連続して 2 回サブスクライブしているため、このオブザーバブルの 2 つのインスタンスはほぼ同時に値を生成しようとします。そのため、値DateTime.Now.Millisecondはほとんどの場合同じですが、現在は常に同じです。から返される値new Random(x).NextDouble()は、同じ に対して同じxであるため、ほとんどの場合、オブザーバブルの 2 つのインスタンスから同じ値を取得するのはなぜですか。DateTime.Now.Millisecond2 つの異なる値が得られるのは が異なる場合だけであり、サブスクライバーの値が欠落しているように見えます。


最初に期待したとおりに動作するはずの代替バージョンを次に示します。

var rnd = new Random((int)DateTime.Now.Ticks);

var numbers =
    Observable
        .Generate(0, n => true, n => 0,
            n => rnd.NextDouble() * 99 + 2,
            n => TimeSpan.FromSeconds(1.0));

var publishedNumbers = numbers.Publish();

publishedNumbers
    .ObserveOnDispatcher()
    .Subscribe(s => list1.Items.Add(s.ToString("##.00")));

publishedNumbers
    .Where(n => n < 10)
    .ObserveOnDispatcher()
    .Subscribe(s => list2.Items.Add(s.ToString("##.00")));

publishedNumbers.Connect();
于 2013-09-11T02:54:56.353 に答える