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


197

完成したTask(ではないTask<T>)を作成したい。これを行うために.NETに組み込まれているものはありますか?

関連質問: 完了したタスクを作成する<T>


2
It seems like the answer I'm getting from everyone is that using a garbage value like this is the correct way. That there isn't a way to do this without the garbage value is disappointing -- oh well.これにはどのような問題があると思いますか?シングルをキャッシュするとTask、プログラム全体で1ビット余分にメモリを消費します。それは何でもない。また、それを実行せずに完了したタスクを作成することもできます。
2013年

10
ああ私の失望は、余分なメモリを使用する必要があることとは何の関係もありません。コードのどこにあるガベージ値もエレガントではないというだけです。
ティモシーシールド2013年

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

回答:


247

.Net(v4.6)最新バージョンは、組み込みのTask.CompletedTaskだけを追加しています

Task completedTask = Task.CompletedTask;

そのプロパティはロックなしのシングルトンとして実装されているため、ほとんどの場合、同じ完了したタスクを使用します。


1
最新のVS 14 CTPを確認し、4.5.3プロジェクトを作成したところ、Task.CompletedTaskまだ内部にあります。
Peter Ritchie

1
2.最新のCTP(4で、そのサイトからリンクされています)をダウンロードしていないか、バージョン4.5.3を指定していません。これが私のマシンにあるものです。@PeterRitchie
i3arnon

AzureのVisual Studio 14イメージからVMを作成しました。
Peter Ritchie


Mac OS Xでモノ5.4.1.7を使用していますが、同じエラーが発生します。どうすれば修正できますか?
Khaled Annajar 2018年

153

Task<T>は暗黙的にに変換できるTaskので、Task<T>T任意の値と任意の値で)完了してそれを使用するだけです。このようなものを使用して、実際の結果がどこかにあるという事実を隠すことができます。

private static Task completedTask = Task.FromResult(false);
public static Task CompletedTask()
{
    return completedTask;
}

結果を公開しておらず、タスクは常に完了しているため、単一のタスクをキャッシュして再利用できます。

.NET 4.0を使用していてFromResult、それがない場合は、次のコマンドを使用して独自に作成できますTaskCompletionSource

public static Task<T> FromResult<T>(T value)
{
    var tcs = new TaskCompletionSource<T>();
    tcs.SetResult(value);
    return tcs.Task;
}

8
4.0を使用している場合は、Microsoft.Bcl.Asyncライブラリを追加してTaskEx.FromResultを取得できます。また、WhenAll
Carl

@Servy FromResult(false)とFromResult(true)から何が変わりますか?
Francesco Bonizzi

3
@FrancescoB。結果を見ていると、結果のブール値が変更されます。結果を無視している場合、結果が何であるかは関係ありません。
サービー

66

これを行うための私の好ましい方法はTask.WhenAll()、引数なしで呼び出すことです。MSDNのドキュメントの状態「付属の配列/列挙は何のタスクが含まれていない場合、返されたタスクは、それが呼び出し元に返される前RanToCompletion状態にすぐに移行します。」という。それはあなたが望むもののように聞こえます。

更新:ソースはMicrosoftのReference Sourceで見つかりました。そこでTask.WhenAllに以下が含まれていることがわかります。

return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait
            Task.CompletedTask :
            new WhenAllPromise(tasks);

したがって、Task.CompletedTaskは確かに内部にありますが、引数なしでWhenAll()を呼び出すことによって公開されます。


9
ちょっとハッキーな感じがしますが、ドキュメントからのサポートがあるので、私は知らない、ちょっと好きです!
サラ1/16

2
私と.NET 4.5.2の制約付きコードについては、十分にエレガントです。ありがとう!
Stas Ivanov 2017

36

私は使用しますTask.Delay(0)。内部的には、完了したのキャッシュされたインスタンスを返しますTask<T>。とにかく、これは現在の回答が推奨することですが、インスタンスを自分でキャッシュする必要はなく、コードに不適切なガベージ値もありません。

Task.Yield()代わりに使用できると思っているかもしれませんが、結果はTask.Yield()is のサブタイプではないことがわかりますがTask、結果はTask.Delay(0)isです。これは2つの違いの1つです。


30

Task.FromResult(.NET 4.5)を使用して、完了したを返すことができますTask<T>

非ジェネリックが必要な場合は、のサブクラスなので、TaskいつでもTask.FromResult(0)または同様に使用できます。Task<T>Task


11

.Net 4.6以降の場合

return Task.CompletedTask;

より低いバージョンのためにあなたは使うことができます

return new Task(() => { });

3
4.6より前のアプローチについては、注意してください。タスクを開始する必要があります。そうしないと完了しません。return Task.Delay(0);代わりに使用してみませんか?
Miquel


0

どうですか:

#pragma warning disable 1998
    public async Task emptyTask() {
    }
#pragma warning restore 1998

気にならない場合は、警告の抑制を省略できます。


メソッドをマークasyncすると、それを使用しなくてもステートマシン装置全体が作成されると思います。したがって、リソースが少ないシナリオでは、空のタスクを返す方が効率的です。
Calvin Fisher、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.