完了したタスクを作成する<T>


125

私はメソッドTask<Result> StartSomeTask()を実装していて、メソッドが呼び出される前にたまたま結果を知っています。すでに完了したTask <T>を作成するにはどうすればよいですか?

これは私が現在やっていることです:

private readonly Result theResult = new Result();

public override Task<Result> StartSomeTask()
{
    var task = new Task<Result>(() => theResult);
    task.RunSynchronously(CurrentThreadTaskScheduler.CurrentThread);
    return task;
}

より良い解決策はありますか?


6
Task <T>はTaskから継承するため、この質問への回答はプレーンタスク(<T>なし)を作成する場合にも問題なく機能します。
Tim Lovell-Smith、

今日ValueTask、完了したタスク(つまり、コードが基本的に同期になるように既に持っている値)があるため、割り当てを節約できることに注意してください。
nawfal 2018年

回答:


111
private readonly Result theResult = new Result();

public override Task<Result> StartSomeTask()
{
    var taskSource = new TaskCompletionSource<Result>();
    taskSource.SetResult(theResult);
    return taskSource.Task;
}

@DanielLoboあなたはあなたの異論が何であるかを説明すればあなたは答えを得るかもしれません
user2023861

1
下のほうが簡単で、賛成票が多いのではないでしょうか。@ user2023861
Daniel Lobo

203

.NET 4.5を対象とする場合、次を使用できますTask.FromResult

public static Task<TResult> FromResult<TResult>(TResult result);

失敗したタスクを作成するには、次を使用しますTask.FromException

public static Task FromException(Exception exception);
public static Task<TResult> FromException<TResult>(Exception exception);

.NET 4.6はTask.CompletedTask、非ジェネリックが必要な場合に追加されますTask

public static Task CompletedTask { get; }

古いバージョンの.NETの回避策:

  • 非同期ターゲットパック(またはAsyncCTP)で.NET 4.0をターゲットにする場合は、TaskEx.FromResult代わりに使用できます。

  • Task.NET 4.6より前の非ジェネリックを取得するにTask<T>は、から派生したファクトを使用して、またはをTask呼び出すだけです。Task.FromResult<object>(null)Task.FromResult(0)


13
非ジェネリックタスクを返すには、Task.FromResult(0)などを使用することをお勧めします。パラメータとして「null」を使用すると、ジェネリックパラメータを判別できないコンパイラを混乱させる可能性があります。
Whyllee 2012年

例外についてはどうですか?非同期メソッドは、例外をキャッチして返されたタスクに保存するステートマシンにコンパイルされます。これは、最初に待機する前に実行されるコードでも発生します。Task.FromResultを返すメソッドが直接例外をスローする場合があります。
RobertVažan2013

@RobertVažan興味深いエッジケース。おそらく、メソッドから既知の結果を取得してい、そのメソッドが例外をスローする場合は、修正が必要な欠陥があります。
Gusdor 2014年

1
@RobertVažan独自のFromExceptionメソッドを簡単に作成できます。このメソッドは、動作は同じですFromResultが、障害のあるタスクを表します。そのようなメソッドは、結果のタスクで例外を表すことが重要である場合、エラーの場合に単にそれを返すことができます。
サービー

1
Task.FromExceptionは.NET 4.5では使用できません...指定する必要があると思います。
STiLeTT 2017年

12

戻り値のないタスクの場合、.NET 4.6はTask.CompletedTaskを追加しました

既にTaskStatus.RanToCompletionにあるタスクを返します。おそらく毎回同じインスタンスを返しますが、ドキュメントはその事実を当てにしないように警告しています。



1

パラメータなしでTask.WhenAllを呼び出すと、完了したタスクが返されます。

Task task = Task.WhenAll();

これは機能しますが、存在しないタスクを待つことを意味するため、コードを読むときに人々を混乱させる可能性があるあいまいな回避策です
Adrian Hristov
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.