Come posso limitare Parallel.ForEach?


295

Ho un ciclo asincrono Parallel.ForEach () con il quale scarico alcune pagine web. La mia larghezza di banda è limitata, quindi posso scaricare solo x pagine alla volta ma Parallel.ForEach esegue l'intero elenco delle pagine Web desiderate.

C'è un modo per limitare il numero di thread o qualsiasi altro limitatore durante l'esecuzione di Parallel.ForEach?

Codice demo:

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

Il vero compito non ha nulla a che fare con le pagine Web, quindi le soluzioni creative di scansione del Web non saranno di aiuto.


@jKlaus Se l'elenco non viene modificato, ad esempio è solo un set di URL, non riesco davvero a vedere il problema?
Shiv

@Shiv, dato il tempo sufficiente ... Conterà il tuo numero di esecuzioni e confrontalo con il conteggio dell'elenco.
jKlaus,

@jKlaus Cosa stai dicendo andrà storto?
Shiv

1
@jKlaus stai modificando un elemento non threadsafe (l'intero). Mi aspetto che non funzioni in quello scenario. L'OP d'altra parte non sta modificando nulla che debba essere sicuro per il thread.
Shiv,

2
@jKlaus Ecco un esempio di Parallel.ForEach che imposta correttamente il conteggio> dotnetfiddle.net/moqP2C . MSDN Link: msdn.microsoft.com/en-us/library/dd997393(v=vs.110).aspx
jhamm

Risposte:


564

È possibile specificare un MaxDegreeOfParallelismin un ParallelOptionsparametro:

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

MSDN: Parallel.ForEach

MSDN: ParallelOptions.MaxDegreeOfPallallelism


59
Potrebbe non essere applicabile a questo caso particolare, ma ho pensato di buttarlo fuori nel caso qualcuno si chiedesse attraverso questo e lo trovasse utile. Qui sto utilizzando il 75% (arrotondato per eccesso) del conteggio del processore. var opts = new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 0.75) * 1.0)) };
jKlaus,

4
Solo per salvare chiunque altro debba cercarlo nella documentazione, passare un valore -1è lo stesso di non specificarlo affatto: "Se [il valore] è -1, non c'è limite al numero di operazioni in esecuzione simultanea"
stuartd,

Non mi è chiaro dalla documentazione: impostare MaxDegreeOfParallelism su 4 (ad esempio) significa che ci saranno 4 thread ciascuno in esecuzione 1/4 delle iterazioni di loop (un giro di 4 thread inviati) o ogni thread fa ancora un loop iterazione e stiamo solo limitando quanti corrono in parallelo?
Hashman

7
Per essere chiari, core e thread non sono la stessa cosa. A seconda della CPU, esiste un numero diverso di thread per core, in genere 2 per core. Ad esempio, se hai una CPU a 4 core con 2 thread per core, hai un massimo di 8 thread. Per regolare il commento di @jKlaus var opts = new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 0.75) * 2.0)) };. Link a thread vs core - askubuntu.com/questions/668538/…
TheMiddleMan

41

Puoi usare ParallelOptions e impostare MaxDegreeOfParallelism per limitare il numero di thread simultanei:

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

21

Utilizzare un altro sovraccarico Parallel.Foreachche richiede ParallelOptionsun'istanza e impostare MaxDegreeOfParallelismper limitare il numero di istanze eseguite in parallelo.


11

E per gli utenti di VB.net (la sintassi è strana e difficile da trovare) ...

Parallel.ForEach(listOfWebpages, New ParallelOptions() With {.MaxDegreeOfParallelism = 8}, Sub(webpage)
......end sub)  
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.