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>
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.
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;
}
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.
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.
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
.
Pour .Net 4.6 et supérieur, utilisez
return Task.CompletedTask;
Pour la version inférieure, vous pouvez utiliser
return new Task(() => { });
Vous pouvez utiliser Nito.AsyncEx.TaskConstants.Completed à partir d'une excellente bibliothèque AsyncEx à partir de Stephen Cleary .
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.