En parallèle.ForEach et asynchrone attendent
J'ai eu une telle méthode:
public async Task<MyResult> GetResult()
{
MyResult result = new MyResult();
foreach(var method in Methods)
{
string json = await Process(method);
result.Prop1 = PopulateProp1(json);
result.Prop2 = PopulateProp2(json);
}
return result;
}
Alors j'ai décidé d'utiliser Parallel.ForEach
:
public async Task<MyResult> GetResult()
{
MyResult result = new MyResult();
Parallel.ForEach(Methods, async method =>
{
string json = await Process(method);
result.Prop1 = PopulateProp1(json);
result.Prop2 = PopulateProp2(json);
});
return result;
}
Mais maintenant j'ai une erreur:
Asynchrone module ou du gestionnaire terminé pendant une opération asynchrone est toujours en attente.
- Où obtenez-vous cette erreur? Je suis en supposant que c'est une exception, elle se produit au sein de
GetResult
? - Est votre
Model
en fait un Modèle de Vue et il met en œuvre INotifyPropertyChanged et est lié à la vue? - Non ce n'est pas un modèle de vue, j'ai probablement à changer de nom. C'est juste un simple
class
avec quelques accessoires - obtention d'exception sur le retour
return result;
- Est
GetResult
affecter la performance? - Ritchie oui, il est.
- Double Possible de Nidification attendent en Parallèle.ForEach
Vous devez vous connecter pour publier un commentaire.
async
ne fonctionne pas bien avecForEach
. En particulier, votreasync
lambda est en train d'être converti enasync void
méthode. Il y a un certain nombre de raisons pour éviter deasync void
(comme je l'ai décrit dans un article MSDN); l'un d'eux est que vous ne pouvez pas facilement détecter si leasync
lambda est terminé. ASP.NET allez voir votre code de retour sans avoir terminé laasync void
méthode et (de manière appropriée) lève une exception.Ce que vous voulez probablement faire est de traiter les données simultanément, tout simplement pas dans parallèle. Code parallèle ne devrait jamais être utilisée sur ASP.NET. Voici à quoi ressemblera le code asynchrone avec le traitement simultané:
Parallel.ForEach
a beaucoup plus d'avantages par rapport à l'aide de matières tâches. Comment sur l'ajustement de laParallel.ForEach
dans une tâche? Cela permettra l'utilisation deasync
lors de l'obtention de tous les avantages de l'utilisation deParallel.ForEach
. Quelque chose comme:Task.Factory.StartNew( () => Parallel.ForEach<Item>(items, item => DoSomething(item)));
Task.Run(() => Parallel...)
est un grand modèle pour pousser le parallèle travailler à partir d'un thread d'INTERFACE utilisateur. Vous ne voulez pas l'utiliser sur ASP.NET cependant.An asynchronous module or handler completed while an asynchronous operation was still pending.
, ce qui se produit seulement sur ASP.NET. Combinant async et le parallélisme dans un processus de travail est très bien.Alternativement, le AsyncEnumerator Package NuGet vous pouvez faire ceci:
où
ParallelForEachAsync
est une méthode d'extension.Ahh, d'accord. Je pense que je sais ce qu'il se passe maintenant.
async method =>
un "async void", qui est "fire and forget" (non recommandé pour autre chose que des gestionnaires d'événements). Cela signifie que l'appelant ne peut pas savoir quand il est terminé... Donc,GetResult
le rendement de l'opération est toujours en cours d'exécution. Bien que les détails techniques de ma première réponse est incorrecte, le résultat est le même: la GetResult est de retour alors que les opérations ont commencé parForEach
sont toujours en cours d'exécution. La seule chose que vous pourriez vraiment faire est de ne pasawait
surProcess
(de sorte que le lambda n'est plusasync
) et attendreProcess
pour terminer chaque itération. Mais, qui va utiliser au moins un thread du pool pour le faire et ainsi le stress de la piscine légèrement--probablement faire usage deForEach
inutile. Je voudrais simplement ne pas utiliser en Parallèle.ForEach...