Non si dovrebbe certamente creare 800 thread.
Facciamo un passo indietro qui. Hai un dispositivo chiamato "server" che accetta "richieste" da "clienti" e invia "risposte" a quei client. Supponiamo che le richieste siano pezzi di carta consegnati dall'ufficio postale e che le risposte siano scatole contenenti libri, anche consegnate dall'ufficio postale.
Si desidera simulare 800 client per testare il server.
Supponiamo che un thread sia una persona e che un processore sia una sedia. Una persona può solo lavorare mentre è seduta sulla sedia.
Creare 800 thread equivale ad uscire e assumere 800 persone e pagare ciascuno di essi per inviare una lettera al server. Ma hai solo quattro sedie, quindi quelle 800 persone devono fare a turno usando le sedie.
Sarebbe una soluzione ridicola nella vita reale. Thread, come le persone, sono follemente costoso. Dovresti ridurre al minimo il numero di thread che crei.
Quindi, dovresti invece creare 800 attività tramite la task factory e lasciare che TPL le parallelizzi per te?
No, non dovresti farlo neanche. Il TPL ha un gruppo di persone (discussioni) da cui attingere, e cerca di sistemare le cose in modo che non ci siano più persone sul libro paga di quante sedie ci siano per loro. Ma il tuo compito non è "legato alla sedia" - - le persone si siederanno sulla sedia, invieranno la richiesta al server, e poi si alzeranno dalla sedia mentre aspettano che la risposta torni. Mentre stanno aspettando, la TPL ora deve assumere più persone per assistere le attività aggiuntive.
Il colpire un server Web è legato all'I/O; è necessario creare solo attività con pool di thread per attività associate alla CPU.
La soluzione giusta è quella di assumere due persone.
Una persona - il "thread di completamento I/O" - non fa altro che eliminare le richieste nella casella di posta e controllare i pacchetti in arrivo. L'altra persona - la persona della "simulazione" - elabora qual è il giusto "programma" per la simulazione di 800 clienti. La persona di simulazione elabora il programma e poi si addormenta. Si sveglia quando è ora di inviare un'altra richiesta al server. Quando si sveglia, dice al thread di completamento dell'I/O di rilasciare questa lettera nella casella di posta e svegliarla quando la risposta arriva. Quindi torna a dormire finché non è il momento di inviare un'altra richiesta o una risposta arriva che deve essere verificato.
Quello che dovresti fare è (1) ottenere la versione beta di C# 5 e usare async/await
per creare attività che inviano richieste al server, e quindi restituire il controllo al ciclo dei messaggi fino a quando non è il momento di inviare un altro richiesta o una risposta arriva. O, se non si desidera utilizzare C# 5, è necessario creare una fonte di completamento attività e impostare attività che hanno le giuste continuazioni.
In breve: il modo corretto per gestire molti compiti di I/O paralleli è creare un numero molto piccolo di thread, ognuno dei quali esegue una quantità minima di lavoro alla volta. Lascia che il thread di completamento I/O gestisca i dettagli dell'I/O. Non è necessario assumere 800 persone per simulare l'invio di 800 lettere. Noleggio due persone, uno per guardare la cassetta postale e uno per scrivere le lettere.
[Vedi discussione correlata qui] (http://stackoverflow.com/questions/10687850/task-factory-startnew-or-parallel-foreach-for-many-long-running-tasks) –