web-dev-qa-db-fra.com

Créer une tâche terminée

Je veux créer un Task terminé (pas Task<T>). Est-ce que quelque chose est intégré à .NET pour faire cela?

Une question connexe: créer une tâche terminée <T>

173
Timothy Shields

La version la plus récente de .Net (v4.6) ajoute précisément cela, une tâche intégrée , ainsi qu'une tâche :

Task completedTask = Task.CompletedTask;

Cette propriété est implémentée en tant que singleton sans verrouillage afin que vous utilisiez presque toujours toujours la même tâche terminée.

219
i3arnon

Task<T> est implicitement convertible en Task, il suffit donc d'obtenir un Task<T> complété (avec n'importe quel T et toute valeur) et l'utiliser. Vous pouvez utiliser quelque chose comme ceci pour cacher le fait qu'un résultat réel est là, quelque part.

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

Notez que, puisque nous n'exposons pas le résultat et que la tâche est toujours terminée, nous pouvons mettre en cache une tâche et la réutiliser.

Si vous utilisez .NET 4.0 et que vous n'avez pas FromResult, vous pouvez créer le vôtre avec TaskCompletionSource:

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

Ma méthode préférée pour cela consiste à appeler Task.WhenAll() sans arguments. Le documentation MSDN indique que "Si le tableau/élément énumérable fourni ne contient aucune tâche, la tâche renvoyée passera immédiatement à l'état RanToCompletion avant d'être renvoyée à l'appelant.". Cela ressemble à ce que vous voulez.

Mise à jour: j'ai trouvé la source sur Source de référence de Microsoft ; vous pouvez voir que Task.WhenAll contient les éléments suivants:

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

Donc, Task.CompletedTask est bien interne, mais il est exposé en appelant WhenAll () sans argument.

63
Richiban

Je voudrais utiliser Task.Delay(0). En interne, il renvoie une instance mise en cache d'un Task<T> terminé. De toute façon, c’est exactement ce que la réponse actuelle suggère de faire. Seulement, maintenant, vous n’avez pas à mettre en cache une instance vous-même, et vous n’avez pas non plus de valeur inélégante dans votre code.

Vous pensez peut-être que vous pouvez utiliser Task.Yield() à la place, mais il s'avère que le résultat de Task.Yield() est pas un sous-type de Task, alors que le résultat de Task.Delay(0) est. C'est l'une des différences subtiles entre les deux.

33
gzak

Vous pouvez utiliser Task.FromResult (dans .NET 4.5) pour renvoyer un Task<T> complété.

Si vous avez besoin d'un Task non générique, vous pouvez toujours utiliser Task.FromResult(0) ou similaire, car Task<T> est une sous-classe de Task.

29
Reed Copsey

Pour .Net 4.6 et supérieur, utilisez

return Task.CompletedTask;

Pour la version inférieure, vous pouvez utiliser

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

Vous pouvez utiliser Nito.AsyncEx.TaskConstants.Completed à partir d'une excellente bibliothèque AsyncEx à partir de Stephen Cleary .

8
Alexander Logger

Que diriez-vous:

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

Vous pouvez omettre la suppression des avertissements si cela ne vous dérange pas.

0
Dorus