Utilizzare delegati asincroni o ThreadPool.QueueUserWorkItem per un parallelismo massiccio?
-
08-07-2019 - |
Domanda
Ho un'applicazione .NET che elabora circa 300.000 record in un'importazione batch e ci vogliono pochi secondi per record, quindi vorrei parallelizzare questo. Nel codice seguente, qual è la differenza tra ProcessWithAnsycDelegates ()
e ProcessWithThreadPool ()
?
public class ResultNotification
{ public EventHandler event Success;
public EventHandler event Fail;
internal void Notify(bool sucess) {if (success) Success(); else Fail();}
}
public static class Processor
{ public ResultNotification ProcessWithAnsycDelegates(Record record)
{ var r = new ResultNotification();
Func<Record,bool> processRecord=new RecordProcessor().ProcessRecord;
processRecord.BeginInvoke
( record
,ar => result.Notify(processRecord.EndInvoke(ar))
,null);
return r;
}
public ResultNotification ProcessWithThreadPool(Record r)
{ var r = new ResultNotification();
var rp = new RecordProcessor();
ThreadPool.QueueWorkUserItem(_=>result.Notify(rp.ProcessRecord(r)));
return r;
}
}
Soluzione
In questo caso, non molto in quanto entrambi usano il threadpool sotto il cofano. Direi che QueueUserWorkItem () è più facile da leggere e vedere cosa sta succedendo vs. BeginInvoke.
Questo link può essere d'aiuto. Sono informazioni più vecchie, ma ancora per lo più applicabili http://www.yoda.arachsys.com/csharp/threads/threadpool.shtml
Altri suggerimenti
La risposta letterale alla domanda è che entrambi usano il threadpool, quindi la differenza non è molto se le prestazioni sono l'unica considerazione.
Se la domanda riguarda davvero le prestazioni migliori, può essere utile sapere che l'utilizzo del threadpool presenta dei problemi. Questi includono:
- Blocca la contesa sulla coda di lavoro
- Cambio di contesto eccessivo. Se hai 2 CPU e una sequenza di elementi di lavoro, 25 thread non aiutano davvero. Meglio avere 2 thread, uno per ogni CPU
Potrebbe valere la pena indagare su TPL e PLINQ:
- Parallel LINQ in esecuzione query su processori multi-core
- Le prestazioni parallele ottimizzano il codice gestito per macchine multi-core
- Supporto migliorato per il parallelismo nella prossima versione di Visual Studio
Un esempio che danno del TPL in uso è:
for (int i = 0; i < 100; i++) {
a[i] = a[i]*a[i];
}
a:
Parallel.For(0, 100, delegate(int i) {
a[i] = a[i]*a[i];
});