375 votes

Comment limiter Parallel.ForEach ?

J'ai une boucle asynchrone Parallel.ForEach() avec laquelle je télécharge des pages web. Ma bande passante étant limitée, je ne peux télécharger que x pages à la fois, mais Parallel.ForEach exécute toute la liste des pages Web souhaitées.

Existe-t-il un moyen de limiter le nombre de threads ou toute autre limite lors de l'exécution de Parallel.ForEach ?

Code démo :

Parallel.ForEach(listOfWebpages, webpage => {
  Download(webpage);
});

La tâche réelle n'a rien à voir avec les pages web, c'est pourquoi les solutions créatives d'exploration du web ne seront d'aucune utilité.

0 votes

@jKlaus Si la liste n'est pas modifiée, c'est-à-dire s'il s'agit simplement d'un ensemble d'URL, je ne vois pas vraiment le problème ?

0 votes

@Shiv, avec un peu de temps, vous... Comptez votre nombre d'exécutions et comparez-le à celui de la liste.

0 votes

@jKlaus Selon vous, qu'est-ce qui va mal se passer ?

699voto

Nicholas Butler Points 12630

Vous pouvez spécifier un MaxDegreeOfParallelism dans un ParallelOptions paramètre :

Parallel.ForEach(
    listOfWebpages,
    new ParallelOptions { MaxDegreeOfParallelism = 4 },
    webpage => { Download(webpage); }
);

MSDN : Parallel.ForEach

MSDN : ParallelOptions.MaxDegreeOfParallelism

84 votes

Il se peut que cela ne s'applique pas à ce cas particulier, mais je me suis dit que j'allais le lancer au cas où quelqu'un tomberait dessus et le trouverait utile. Ici, j'utilise 75% (arrondi) du nombre de processeurs. var opts = new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 0.75) * 1.0)) };

7 votes

Pour éviter à quiconque d'avoir à le vérifier dans la documentation, le fait de passer une valeur de -1 revient à ne pas le spécifier du tout : "Si [la valeur] est -1, il n'y a pas de limite au nombre d'opérations exécutées simultanément.

1 votes

La documentation n'est pas claire pour moi - est-ce que le fait de fixer MaxDegreeOfParallelism à 4 (par exemple) signifie qu'il y aura 4 threads qui exécuteront chacun 1/4 des itérations de la boucle (un tour de 4 threads distribués), ou est-ce que chaque thread fait toujours une itération de la boucle et nous limitons simplement le nombre de threads exécutés en parallèle ?

62voto

rikitikitik Points 1723

Vous pouvez utiliser ParallelOptions et définir MaxDegreeOfParallelism pour limiter le nombre de threads simultanés :

Parallel.ForEach(
    listOfwebpages, 
    new ParallelOptions{MaxDegreeOfParallelism=2}, 
    webpage => {Download(webpage);});

25voto

Richard Points 54016

Utilisez une autre surcharge de Parallel.Foreach qui prend un ParallelOptions et définir l'instance MaxDegreeOfParallelism pour limiter le nombre d'instances exécutées en parallèle.

17voto

user3496060 Points 383

Et pour les utilisateurs de VB.net (la syntaxe est bizarre et difficile à trouver)...

Parallel.ForEach(listOfWebpages, New ParallelOptions() With {.MaxDegreeOfParallelism = 8}, Sub(webpage)
......end sub)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X