Je veux créer un Task
(pas Task<T>
) terminé . Y a-t-il quelque chose de intégré à .NET pour ce faire?
Une question connexe: créer une tâche terminée <T>
c#
.net
async-await
task-parallel-library
Timothy Shields
la source
la source
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.
Quels problèmes pensez-vous que cela a? Si vous en cachez un seul,Task
votre programme entier prend un bit de mémoire supplémentaire. Ce n'est rien . De plus, on pourrait créer une tâche terminée sans le faire, ce ne serait pas mieux.ValueTask
des tâches terminées (c'est-à-dire pour les valeurs que vous avez déjà afin que le code soit essentiellement synchrone), ce qui vous fera économiser une allocation.Réponses:
La dernière version de .Net (v4.6) ajoute juste cela, une tâche intégrée .
Cette propriété est implémentée comme un singleton sans verrouillage, vous utiliserez donc presque toujours la même tâche terminée.
la source
Task.CompletedTask
est toujours interne.Task<T>
est implicitement convertible enTask
, donc obtenez simplement unTask<T>
(avec n'importeT
quelle valeur) et utilisez-le. Vous pouvez utiliser quelque chose comme ça pour cacher le fait qu'un résultat réel est là, quelque part.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 seule tâche et la réutiliser.
Si vous utilisez .NET 4.0 et n'en avez pas,
FromResult
vous pouvez créer le vôtre en utilisantTaskCompletionSource
:la source
Ma méthode préférée pour ce faire est d'appeler
Task.WhenAll()
sans argument. La documentation MSDN indique que "Si le tableau / énumérable fourni ne contient aucune tâche, la tâche renvoyée passera immédiatement à un état RanToCompletion avant d'être renvoyée à l'appelant.". Cela ressemble à ce que vous voulez.Mise à jour: j'ai trouvé la source sur la source de référence de Microsoft ; là, vous pouvez voir que Task.WhenAll contient les éléments suivants:
Donc Task.CompletedTask est en effet interne, mais il est exposé en appelant WhenAll () sans arguments.
la source
J'utiliserais
Task.Delay(0)
. En interne, il renvoie une instance mise en cache d'un terminéTask<T>
. C'est exactement ce que la réponse actuelle suggère de faire de toute façon, seulement maintenant vous n'avez pas à mettre en cache une instance vous-même, et vous n'avez pas non plus de valeurs inutiles dans votre code.Vous pensez peut-être que vous pouvez utiliser à la
Task.Yield()
place, mais il s'avère que le résultat deTask.Yield()
n'est pas un sous-type deTask
, tandis que le résultat deTask.Delay(0)
est. C'est l'une des subtiles différences entre les deux.la source
Vous pouvez utiliser Task.FromResult (dans .NET 4.5) pour renvoyer une requête terminée
Task<T>
.Si vous avez besoin d'un non générique
Task
, vous pouvez toujours utiliserTask.FromResult(0)
ou similaire, car ilTask<T>
s'agit d'une sous-classe deTask
.la source
Pour .Net 4.6 et supérieur, utilisez
Pour la version inférieure, vous pouvez utiliser
la source
return Task.Delay(0);
place?Vous pouvez utiliser Nito.AsyncEx.TaskConstants.Completed à partir d'une excellente bibliothèque AsyncEx de Stephen Cleary .
la source
Que diriez-vous:
Vous pouvez ignorer la suppression des avertissements si cela ne vous dérange pas.
la source
async
crée toujours l'appareil de la machine d'état entière même si vous ne l'utilisez pas, donc retourner une tâche vide est plus efficace pour les scénarios à faibles ressources.