J'ai peu de services REST asynchrones qui ne dépendent pas les uns des autres. C'est en "attendant" une réponse de Service1, je peux appeler Service2, Service3 et ainsi de suite.
Par exemple, reportez-vous au code ci-dessous:
var service1Response = await HttpService1Async();
var service2Response = await HttpService2Async();
// Use service1Response and service2Response
Maintenant, service2Response
ne dépend pas service1Response
et ils peuvent être récupérés indépendamment. Par conséquent, il n'est pas nécessaire que j'attende la réponse du premier service pour appeler le deuxième service.
Je ne pense pas pouvoir l'utiliser Parallel.ForEach
ici car ce n'est pas une opération liée au CPU.
Pour appeler ces deux opérations en parallèle, puis-je appeler use Task.WhenAll
? Un problème que je vois utiliser Task.WhenAll
est qu'il ne renvoie pas de résultats. Pour récupérer le résultat, puis-je appeler task.Result
après avoir appelé Task.WhenAll
, car toutes les tâches sont déjà terminées et tout ce dont j'ai besoin pour nous récupérer la réponse?
Exemple de code:
var task1 = HttpService1Async();
var task2 = HttpService2Async();
await Task.WhenAll(task1, task2)
var result1 = task1.Result;
var result2 = task2.Result;
// Use result1 and result2
Ce code est-il meilleur que le premier en termes de performances? Une autre approche que je peux utiliser?
la source
I do not think I can use Parallel.ForEach here since it is not CPU bound operation
- Je ne vois pas la logique là-bas. La concurrence est la concurrence.Parallel.ForEach
engendrerait de nouveaux threads alorsasync await
qu'il ferait tout sur un seul thread.await
) avant qu'il ne soit prêt.WhenAll
avant de faireResult
avec l'idée qu'il termine toutes les tâches avant que .Result soit appelé. Depuis, Task.Result bloque le thread appelant, je suppose que si je l'appelle une fois les tâches terminées, il retournerait immédiatement le résultat. Je veux valider la compréhension.Réponses:
Mais il ne renvoie les résultats. Ils seront tous dans un tableau d'un type commun, il n'est donc pas toujours utile d'utiliser les résultats dans la mesure où vous devez trouver l'élément dans le tableau qui correspond à
Task
celui pour lequel vous voulez le résultat, et potentiellement le caster dans son type réel, donc ce n'est peut-être pas l'approche la plus facile / la plus lisible dans ce contexte, mais quand vous voulez juste avoir tous les résultats de chaque tâche, et le type commun est le type que vous voulez traiter, alors c'est génial .Oui, tu peux le faire. Vous pouvez également
await
lesawait
utiliser ( déballer l'exception dans toute tâche défectueuse, alorsResult
que lancer une exception agrégée, mais sinon ce serait la même chose).Il effectue les deux opérations en même temps, plutôt que l'une puis l'autre. Que ce soit meilleur ou pire dépend de ce que sont ces opérations sous-jacentes. Si les opérations sous-jacentes sont "lire un fichier à partir du disque", alors les faire en parallèle est probablement plus lent, car il n'y a qu'une seule tête de disque et elle ne peut être à un endroit à un moment donné; passer d'un fichier à l'autre sera plus lent que de lire un fichier puis un autre. D'un autre côté, si les opérations "effectuent une requête réseau" (comme c'est le cas ici), elles seront très probablement plus rapides (au moins jusqu'à un certain nombre de requêtes simultanées), car vous pouvez attendre une réponse à partir d'un autre ordinateur réseau tout aussi rapidement lorsqu'il y a également une autre demande réseau en attente. Si tu veux savoir si c'est
S'il n'est pas important pour vous que vous connaissiez toutes les exceptions levées parmi toutes les opérations que vous effectuez en parallèle plutôt que juste la première, vous pouvez simplement effectuer
await
les tâches sans rienWhenAll
du tout. La seule chose queWhenAll
vous donne est d'avoir unAggregateException
avec chaque exception unique de chaque tâche défectueuse, plutôt que de lancer lorsque vous frappez la première tâche défectueuse. C'est aussi simple que:la source
Voici la méthode d'extension qui utilise SemaphoreSlim et permet de définir le degré maximum de parallélisme
Exemple d'utilisation:
la source
Vous pouvez soit utiliser
ou
la source