13

両方と、それらを一緒に使用する方法を学びたいだけです。それらが互いに補完し合うことができることは理解していますが、実際に誰かがそれを行っている例を見つけることができませんでした.

4

1 に答える 1

21

少し背景から始めましょう。

.NET フレームワークには、基になる型に特別な機能を提供する、適切なクラスまたはインターフェイスのいずれかである、、、、、などの特殊な型がTask<T>多数あります。IObservable<T>Nullable<T>IEnumerable<T>Lazy<T>T

TPL はTask<T>、 の単一値の非同期計算を表すために使用しますT

Rx はIObservable<T>、 の 0 個以上の値の非同期計算を表すために使用しますT

TPL と Rx を結び付けるのは、これら両方の「非同期計算」の側面です。

現在、TPL は型Taskを使用してラムダの非同期実行も表していますが、これはwhere isActionの特殊なケースと見なすことができます。C# の標準メソッドと非常によく似ており、次のように返されます。Task<T>Tvoidvoid

public void MyMethod() { }

Rx は、 と呼ばれる特殊なタイプを使用して、同じ特殊なケースも可能にしますUnit

TPL と Rx の違いは、返される値の数にあります。TPL は 1 つだけですが、Rx は 0 以上です。

したがって、Rx を特別な方法で扱い、単一の値を返すオブザーバブル シーケンスのみを処理する場合、TPL と同様の方法でいくつかの計算を行うことができます。

たとえば、TPL では次のように記述できます。

Task.Factory
    .StartNew(() => "Hello")
    .ContinueWith(t => Console.WriteLine(t.Result));

Rx では、次のようになります。

Observable
    .Start(() => "Hello")
    .Subscribe(x => Console.WriteLine(x));

次のように TPL を使用して計算を実行するように指定することで、Rx でさらに一歩進めることができます。

Observable
    .Start(() => "Hello", Scheduler.TaskPool)
    .Subscribe(x => Console.WriteLine(x));

(デフォルトでは、スレッド プールが使用されます。)

これで、「ミキシングとマッチング」を行うことができました。名前空間への参照を追加すると、System.Reactive.Threading.Tasksタスクとオブザーバブルの間を簡単に移動できます。

Task.Factory
    .StartNew(() => "Hello")
    .ToObservable()
    .Subscribe(x => Console.WriteLine(x));

Observable
    .Start(() => "Hello")
    .ToTask()
    .ContinueWith(t => Console.WriteLine(t.Result));

ToObservable()&の.ToTask()呼び出しと、その結果の 1 つのライブラリから別のライブラリへの反転に注意してください。

複数の値を返すオブザーバブルがある場合、オブザーバブル.ToArray()拡張メソッドを使用して、複数のシーケンス値をタスクに変換できる単一の配列値に変換できます。そのようです:

Observable
    .Interval(TimeSpan.FromSeconds(1.0))
    .Take(5) // is IObservable<long>
    .ToArray()
    .ToTask() // is Task<long[]>
    .ContinueWith(t => Console.WriteLine(t.Result.Length));

これはあなたの質問に対するかなり基本的な答えだと思います。それはあなたが期待していたものですか?

于 2012-07-10T12:56:23.000 に答える