De la tâche.Usine.StartNew avec async lambda et de la Tâche.WaitAll
Je suis en train d'utiliser Task.WaitAll
sur une liste de tâches. Le truc, c'est que les tâches sont un async lambda qui rompt Tasks.WaitAll
comme il n'attend jamais.
Voici un exemple de bloc de code:
List<Task> tasks = new List<Task>();
tasks.Add(Task.Factory.StartNew(async () =>
{
using (dbContext = new DatabaseContext())
{
var records = await dbContext.Where(r => r.Id = 100).ToListAsync();
//do long cpu process here...
}
}
Task.WaitAll(tasks);
//do more stuff here
Cela ne veut pas attendre, car le lambda asynchrone. Alors, comment suis-je censé attendre opérations d'e/S dans ma lambda?
- Quel est le point de commencer une tâche sur un autre thread si la première chose que vous faites après que vous commencez, il est bloquer sur le
Task.WaitAll
appel? Vous obtiendrez de meilleures performances se débarrasser deToListAsync
et de le rendre justeToList
et en l'exécutant en mode synchrone. (ou si vous voulez utiliserToListAsync
ensuite, vous devez utiliser asynchrone tout en haut de votre pile d'appel.
Vous devez vous connecter pour publier un commentaire.
Task.Factory.StartNew
ne reconnaît pasasync
délégués qu'il n'y a pas de surcharge qui accepte une fonction retournant uneTask
.Cela en plus d'autres raisons (voir StartNew est dangereux) est pourquoi vous devriez être en utilisant
Task.Run
ici:TaskCreationOptions
Task.Factory.StartNew(Func<Task> function
semble être disponible dans .NET Standard 1.6 - l'on peut avoir àUnwrap()
l'résultantTask
bien 🙂La raison
Task.WaitAll
ne pas attendre l'achèvement de l'OI travail présenté par votre async lambda est parce queTask.Factory.StartNew
retourne en fait unTask<Task>
. Depuis votre liste est uneList<Task>
(etTask<T>
dérive deTask
), vous vous attendez à l'extérieur de la tâche a commencé parStartNew
, tandis que ignorant l'intérieur créé par le lambda asynchrone. C'est pourquoi ils disentTask.Factory.StartNew
est dangereux à l'égard de async.Comment pouvez-vous résoudre ce problème? Vous pourriez appeler explicitement
Task<Task>.Unwrap()
afin d'obtenir l'intérieure de la tâche:Ou comme d'autres ont dit, vous pouvez l'appeler
Task.Run
à la place:Aussi, puisque vous voulez faire les choses, vous aurez envie d'utiliser
Task.WhenAll
, pourquoi est asynchrone waitable, au lieu deTask.WaitAll
qui synchrone blocs:Vous pouvez faire comme ceci.
Task.WaitAll
si vous utilisezasync
parce que vous pouvez facilement l'impasse.vous devez utiliser le
Task.ContinueWith
méthode. Comme ce