2

私はRxを初めて使用し、いくつかのサンプルを調べていて、以下に出くわしました:

    Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(
            h => new RoutedEventHandler(h),
            h => Loaded += h,
            h => Loaded -= h)
            .Select(_ => true)
            .StartWith(IsLoaded)
            .Where(l => l)
            .Take(1)
            .Subscribe(_ => Console.WriteLine("loaded");

このステートメントを分解して、それが何をしているのかを理解しようとしていますが、100% 明確ではありません。

FromEventPatternLoadedイベントを監視可能なシーケンスに変換する方法を理解しています。ここで、IsLoadedが true のときにSelectがトリガーされます (これが私が想定していることです)。SelectはRoutedEventArgs から情報を取得しているだけですか?

ここで、StartsWithが存在する理由がわかりません。 StartsWithは、オブザーバブル シーケンスの先頭に一連の値を追加します。IsLoadedの値をリストの先頭に追加するだけですか? Selectが発生した後、既にそこにあるのではないでしょうか?

.Whereはいかなる種類のフィルターも適用しないため、.Takeはシーケンスの最初の値のみを取得します (この場合、それ以上は使用されません)。次にサブスクライブし、コントロールがロードされたときにのみコンソールに書き込まれます。

この分析はおおむね正しいですか?

また、そのようなものをデバッグするためのヒント (つまり、チェーンのさまざまな段階でシーケンスがどのように見えるか) はありますか? デバッガーをアタッチするだけで情報を取得できますが、一般的に使用される可能性のある他のトリック/ヒントがあるかどうか疑問に思っていました。

4

2 に答える 2

4

Observable オペレーターのほとんどは、同じ名前の Enumerable オペレーターと同じように機能します。それらを使用した経験がある場合は、ここで役立ちます。

これを解決するために、少しの間、オブザーバブルの代わりに整数の配列を使用しましょう。

int[] data = {1, 2, 3, 4};

これにより、式が次のように変わります。

var results = data.Select(_ => true) 
                  .StartWith(IsLoaded)
                  .Where(l => l)
                  .Take(1);
foreach (var r in results)
{
    Console.WriteLine("loaded");
}

式の各段階で配列を作成すると、次のようになります。

Select - {true, true, true, true}
StartWith - {value of IsLoaded, true, true, true, true}
Where - (if IsLoaded is true)  {true, true, true, true, true}
        (if IsLoaded is false) {true, true, true, true}
Take - {true}

IEnumerables では、この種のことを行うことはあまり意味がありません。なぜなら、ソース配列が空で、IsLoaded が false でない限り、常に 1 つの値が true になるからです。

これを IObservable で使用すると、オブジェクトがロードされたときに 1 つのシグナルを生成するものを作成できます。

  • これStartWithは、サブスクリプション時にオブジェクトがすでにロードされている場合にシグナルを提供します。
  • ただし、オブジェクトがロードされていない場合はIsLoadedfalse になり、Whereフィルターで除外され、イベントが発生すると通知がトリガーされます。
    • Select、イベントによって生成された実際のデータを無視し、単純に true を渡します。これはWhereフィルターを通過します。
  • は、オブジェクトがすでにロードされているため通知が から来るか、ロードが完了したときに ( を介して)イベントTakeから来るかに関係なく、通知を 1 回だけトリガーするために使用されます。StartWithSelect
于 2012-10-05T16:26:28.427 に答える
2

Rx を初めて使用し、各オペレーターが何を行うかを明確にする必要がある場合は、Rx Sandboxを試すことができます。これは古いバージョンの Rx を使用しますが、v2 に進む前に v1 から学ぶことができるでしょう。ストリームでコンビネータを視覚化して試すことができ、結果をマーブル ダイアグラムとして表示できます。

Zipこれがオペレーターの表現です。

Rx マーブル ダイアグラム ビューア

いずれかのストリームからの 2 つの値をペアにすることは簡単にわかります。

シーケンスをデバッグする簡単な方法はDo、次のように間に演算子を使用することです。

    static IObservable<T> Log<T>(this IObservable<T> stream, string name)
    {
        return stream.Materialize()
                     .Do(n => Console.WriteLine("{0} - {1}",name, n))
                     .Dematerialize();
    }

例:

        Observable.Interval(TimeSpan.FromSeconds(0.5))
                  .Log("Timer")
                  .Where(i => i % 2 == 0)
                  .Log("Where")
                  .Sample(TimeSpan.FromSeconds(2))
                  .Log("Sample")
                  .Take(1)
                  .Log("Take")
                  .Subscribe();

各値がパイプラインを下って伝播するのを確認できます。

Timer - OnNext(0)
Where - OnNext(0)
Timer - OnNext(1)
Timer - OnNext(2)
Where - OnNext(2)
Timer - OnNext(3)
Sample - OnNext(2)
Take - OnNext(2)
Take - OnCompleted()
于 2012-10-06T05:57:01.780 に答える