11

作業中のタスクのリストがある状況にあります (ドライブを有効にする、位置を変更する、停止を待つ、無効にする)。

「待機」は、IObservable<Status>待機したい を監視します (そのためContinueWith、他のタスクをスレッド化できます)。

サブスクライバーの OnNext 処理内で次のタスクを開始しましたが、それは見苦しかったです。私が今思いついたのは、この拡張メソッドです:

public static Task<T> WaitFor<T>(this IObservable<T> source, Func<T, bool> pred)
{
    var tcs = new TaskCompletionSource<T>();
    source
        .Where(pred)
        .DistinctUntilChanged()
        .Take(1)  //OnCompletes the observable, subscription will self-dispose
        .Subscribe(val => tcs.TrySetResult(val),
                    ex => tcs.TrySetException(ex),
                    () => tcs.TrySetCanceled());

    return tcs.Task;
}

( svickの取り扱いの提案でOnCompleted更新OnError)

質問:

  • これは良いですか、悪いですか、それとも醜いですか?
  • これを行うことができた既存の拡張機能を見逃しましたか?
  • WhereDistinctUntilChangedの順序は正しいですか? (私は彼らだと思います
4

2 に答える 2

13

少なくとも、この拡張メソッドを次のように変更します。

public static Task<T> WaitFor<T>(this IObservable<T> source, Func<T, bool> pred)
{
    return
        source
            .Where(pred)
            .DistinctUntilChanged()
            .Take(1)
            .ToTask();
}

を導入するよりも、使用する.ToTask()方がはるかに優れていTaskCompletionSourceます。拡張メソッドSystem.Reactive.Threading.Tasksを取得するには、名前空間への参照が必要です。.ToTask()

また、DistinctUntilChangedこのコードでは冗長です。取得できる値は 1 つだけなので、既定では異なる必要があります。

さて、私の次の提案は少し物議をかもすかもしれません。この拡張は、何が起こっているかの真のセマンティクスを隠してしまうため、悪い考えです。

次の 2 つのコード スニペットがあるとします。

var t = xs.WaitFor(x => x > 10);

または:

var t = xs.Where(x => x > 10).Take(1).ToTask();

何が起こっているのかを明確に示しているので、私は通常、2 番目のスニピットを好みますWaitFor

の名前をよりわかりやすい名前にしない限り、WaitForおそらくTakeOneAsTaskWhere、演算子を使用するコードから演算子を使用することの明快さを取り除き、コードの管理を難しくしています。

以下はセマンティクスを覚えやすくしませんか?

var t = xs.TakeOneAsTaskWhere(x => x > 10);

私にとっての結論は、Rx 演算子はカプセル化されたものではなく、構成されたものであるということですが、カプセル化する場合は、その意味を明確にする必要があります。

これが役立つことを願っています。

于 2012-07-30T09:25:59.363 に答える
3

これについては100%確実ではありませんが、Rx 2.0ベータブログの投稿を読むと、async / awaitを使用できる場合は、「return await source.FirstAsync(pred)」または非同期なしで「returnsource.FirstAsync」が可能だと思います。 (pred).ToTask() "

http://blogs.msdn.com/b/rxteam/archive/2012/03/12/reactive-extensions-v2-0-beta-available-now.aspx

rx2.0とfirstasyncを使用したlinqpadのショット

于 2012-07-30T14:11:09.180 に答える