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.