2

Rx について学ぶ中で、 The Observable Contractで詳しく説明されている、Observableに関する頻繁に繰り返されるルールに出くわしました。

OnCompleted または OnError 通知を発行すると、それ以降は通知を発行できません。

Observable が完了した後も値を生成し続けると混乱するため、これは理にかなっていますが、.NET で Observable.Range メソッドをテストしたところ、その動作を示さないことに気付きました。多くのObservable がこのルールに違反しています。

var rangeObservable = Observable.Range(0, 5);

rangeObservable.Subscribe(Console.WriteLine, () => Console.WriteLine("Done first!"));
Console.ReadLine();

rangeObservable.Subscribe(Console.WriteLine, () => Console.WriteLine("Done second!"));
Console.ReadLine();

//Output:
//0
//1
//2
//3
//4
//Done first!

//0
//1
//2
//3
//4
//Done second!

明らかに2 回rangeObservable呼び出され、最初の の後に値が生成されました。これは、これがObservablesに関する規則ではなく、 Subscriptionsに関する規則であると私に信じさせます。つまり、各サブスクリプションが 1 つの終了メッセージのみを受信し、それ以降メッセージを受信しない限り、 Observableは必要な数の終了メッセージを生成し、その後に値を生成することさえできます。OnCompleteOnComplete

Observableと表示されている場合、実際にはSubscriptionを意味しますか? それらは本当に別のものですか?モデルについて根本的な誤解がありますか?

4

2 に答える 2

4

Observable.Rangeコールドオブザーバブルを返します。つまり、各サブスクライバーの動作を「再生」します。「OnNext* OnComplete|OnError」コントラクトはサブスクリプションにのみ適用されるため、これはまったく問題ありません。

ホット/コールド オブザーバブルの詳細については、「Rx の IConnectableObservables」に関する私の回答を参照してください。

于 2016-12-31T10:21:07.040 に答える
4

オブザーバブル コントラクトは、観察されるすべてのオブザーバブルに対して有効である必要があります。Observable が監視されていない間に何かが発生するかどうかは、Observable の実装に任されています。

Enumerable のアナログと、Enumerable の双対である Observable を考えると役立ちます。列挙型では、 があり range = Enumerable.Range(0, 5)、上記のような範囲を使用します。

range.ForEach(Console.WriteLine); //prints 0 - 4

range.ForEach(Console.WriteLine); //prints 0 - 4 again

GetEnumerator実際のナンバ ジェネレータはが呼び出されたときにのみ作成されるため、これが完全に許容される動作であることがわかります。同様に、Observable では、同等のメソッドはSubscribe.

range の実​​装は次のようになります。

        static IObservable<int> Range(int start, int count)
        {
            return Observable.Create<int>(observer =>
            {
                for (int i = 0; i < count; i++)
                    observer.OnNext(start + i);

                observer.OnCompleted();

                return Disposable.Empty;
            });
        }

ここでobserver => {...}は、サブスクリプションがあるたびに関数が呼び出されます。作業は subscribe メソッドで行われます。(1) すべてのオブザーバーに対して同じシーケンスをプッシュすること、(2) オブザーバーごとに 1 回だけ完了することが簡単にわかります。

観察したときにのみ何かが起こるこれらのオブザーバブルは、コールドオブザーバブルと呼ばれます。コンセプトを説明した記事です。

ノート

Range、説明のみを目的とした非常に単純な実装です。このメソッドは、完了するまで使い捨てを返さないため、Disposable.Empty許容されます。適切な実装では、スケジューラで作業を実行し、checkeddisposable を使用して、ループを続行する前にサブスクリプションが破棄されているかどうかを確認します。

要点は、オブザーバブル コントラクトを手動で実装するのは難しいということです。これが Rx ライブラリが存在する理由です。構成によって機能を構築するためです。

于 2016-12-31T06:21:25.257 に答える