C#でのTask.FromResult <TResult>の用途は何ですか


189

C#およびTPL(Task Parallel Library)では、TaskクラスはT型の値を生成する進行中の作業を表します。

Task.FromResultメソッドの必要性は何ですか?

つまり、すでに生成された値を手元に持っているシナリオで、それをタスクにラップする必要性は何ですか?

頭に浮かぶのは、Taskインスタンスを受け入れる他のメソッドのアダプターとして使用されることだけです。


4
これはあなたを助けますか?msdn.microsoft.com/en-us/library/hh228607.aspx
Izikon 2013年

30
ある程度はそれに同意しますが、このような高密度で有用な統合されたディスカッション指向のページを作成することは、大きなメリットです。ほとんどの場合、グーグルや複数の場所での調査よりも、優れた高密度のスタックオーバーフローページから多くを学ぶので、この場合、彼がこれを投稿して本当に嬉しいです。
Alex Edelstein

41
Googleが私をSOに連れて行ってくれて、Googleに行くように頼んでいると思います。これは循環参照です:)
gmailユーザー

回答:


257

私が見つけた2つの一般的な使用例があります。

  1. 非同期の呼び出しを許可するインターフェイスを実装しているが、実装は同期的である場合。
  2. テストのために非同期コードをスタブ/モックするとき。

6
#1の良い例はWebサービスです。戻る同期サービスメソッドとTask.FromResult、ネットワークI / Oを非同期的に待機するクライアントを使用できます。これにより、を使用してクライアント/サーバー間で同じインターフェースを共有できますChannelFactory
Nelson Rothermel 2014

2
たとえば、ChallengeAsyncメソッドです。WTFは、MSのデザイナーは考えていましたか?このメソッドがタスクを返す理由はまったくありません。そして、MSからのすべてのサンプルコードは、単にFromResult(0)を持っています。うまくいけば、コンパイラはこれをすぐに最適化するのに十分スマートであり、実際には新しいスレッドを生成してすぐに強制終了しない!
John Henckel、2015年

14
@JohnHenckel:OWINは非同期に対応するようにゼロから設計されています。インターフェースと基本クラスは、実装が非同期であることを強制ではなく)許可するだけなので、しばしば非同期署名を使用します。だから、それはからIEnumerable<T>派生するのに似てIDisposableます -それは強制的にではなく、列挙型が使い捨てのリソースを持つことを可能にします。どちらもFromResultasync、もawaitのスレッドを生成しません。
Stephen Cleary

4
@StephenCleary hmhm、それを説明してくれてありがとう。私はawaitがスポーンすることを想定していましたが、試してみましたが、そうではありません。Task.Runのみが行います。したがって、x = await Task.FromResult(0); x = 0と言うのと同じです。わかりにくいですが、知っておくと便利です。
John Henckel、2015年

4
@OlegI:I / Oオペレーションの場合、最善の解決策は非同期で実装することですが、その選択肢がない場合もあります。また、同期的に実装できる場合もあります(キャッシュされた結果、値がキャッシュされていない場合は非同期実装にフォールバックするなど)。より一般的には、Task-returningメソッドは「非同期かもしれません」を意味します。したがって、メソッドには、一部の実装が同期することを十分に理解している非同期シグネチャが与えられることがあります(たとえば、NetworkStream非同期であるMemoryStream必要がありますが、同期する必要があります)。
Stephen Cleary

50

1つの例は、キャッシュを利用するメソッドです。結果がすでに計算されている場合は、値を使用して完了したタスクを返すことができます(を使用Task.FromResult)。そうでない場合は、先に進み、進行中の作業を表すタスクを返します。

キャッシュの例:事前計算された値にTask.FromResultを使用したキャッシュの例


また、から返されたタスクなどの完了したタスクをTask.FromResultキャッシュできます。
Paulo Morgado 2013年

1
@Paulo:タスクオブジェクト全体をメモリに保持することは、結果だけをキャッシュするよりもはるかに無駄が多いようです。
Ben Voigt 2014年

2
「バリュータスク」がすでにキャッシュされていることを期待してください。私は正確にどのものを覚えていませんが、私が思うにTask.FromResult(0)Task.FromResult(1)Task.FromResult(false)およびTask.FromResult(true)キャッシュされます。ネットワークアクセスのタスクをキャッシュすることは想定されていませんが、結果からのタスクは完全に問題ありません。値を返す必要があるたびに作成しますか?
Paulo Morgado 2014年

4
...そして私の質問に答えると、タスクのキャッシュの利点は、タスクの一部を完了できることと、まだ完了していないタスクがあることです。呼び出し元は気にする必要はありません。非同期呼び出しを実行します。呼び出しが既に完了している場合は、待機したときにすぐに応答を受け取り、そうでない場合は後で応答します。これらのキャッシュされたタスクがない場合、(a)2つの異なるメカニズム、1つは同期と1つは非同期-呼び出し元にとって煩わしい、または(b)呼び出し元がすでに利用可能な回答を要求するたびに動的にタスクを作成する必要があります( TResultをキャッシュするだけでした)。
ToolmakerSteve

1
わかった。答えの言い回しは少し混乱しました。タスク自体には、「キャッシュ」メカニズムが組み込まれていません。しかし、たとえば....ファイルのダウンロード、Task <File> GetFileAync()のキャッシュメカニズムを記述した場合、Task.FromResult(cachedFile)を使用して、すでにキャッシュにあるファイルを即座に返すことができます。同期的に実行され、スレッドを切り替えないことで時間を節約します。
Brain2000

31

asyncキーワードを使用せずに待機可能なメソッドを作成する場合に使用します。私はこの例を見つけました:

public class TextResult : IHttpActionResult
{
    string _value;
    HttpRequestMessage _request;

    public TextResult(string value, HttpRequestMessage request)
    {
        _value = value;
        _request = request;
    }
    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage()
        {
            Content = new StringContent(_value),
            RequestMessage = _request
        };
        return Task.FromResult(response);
    }
}

ここでは、Web APIアクションで使用されるIHttpActionResultインターフェイスの独自の実装を作成しています。ExecuteAsyncメソッドは非同期であることが期待されますが、非同期で待機可能にするためにasyncキーワードを使用する必要はありません。すでに結果があり、何も待つ必要がないので、Task.FromResultを使用することをお勧めします。



4

非同期操作が必要な場合にTask.FromResultを使用しますが、結果が同期的に得られることもあります。http://msdn.microsoft.com/en-us/library/hh228607.aspxで適切なサンプルを見つけることができます。


あなたの良いサンプルでは、​​結果は同期的に手にありません、操作はすべて非同期で、Task.FromResult以前にキャッシュされた非同期結果を取得するために使用されます。
ロドリゴレイス

1

コードで他の独立した作業を行うことができる一方で、完了までに長い時間がかかる同期的なメソッドにTask.FromResultを使用できると私は主張します。ただし、これらのメソッドを非同期で呼び出すようにしてください。しかし、呼び出されたコードを制御できず、暗黙の並列処理が必要な状況を想像してみてください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.