Altre risposte qui sembrano tralasciare il punto più importante:
A meno che tu non stia cercando di parallelizzare un'operazione che richiede molta CPU per farla più velocemente su un sito a basso carico, non ha alcun senso usare un thread di lavoro.
Ciò vale sia per i thread gratuiti, creati da new Thread(...)
, sia per i thread di lavoro in ThreadPool
che rispondono alle QueueUserWorkItem
richieste.
Sì, è vero, puoi morire di fame ThreadPool
in un processo ASP.NET accodando troppi elementi di lavoro. Impedirà ad ASP.NET di elaborare ulteriori richieste. Le informazioni contenute nell'articolo sono accurate a tale riguardo; lo stesso pool di thread utilizzato per QueueUserWorkItem
viene utilizzato anche per servire le richieste.
Ma se stai effettivamente mettendo in coda abbastanza elementi di lavoro da causare questa fame, allora dovresti morire di fame il pool di thread! Se stai eseguendo letteralmente centinaia di operazioni che richiedono un uso intensivo della CPU allo stesso tempo, a cosa sarebbe utile avere un altro thread di lavoro per servire una richiesta ASP.NET, quando la macchina è già sovraccarica? Se ti trovi in questa situazione, devi riprogettare completamente!
La maggior parte delle volte vedo o sento parlare di codice multi-thread utilizzato in modo inappropriato in ASP.NET, non è per accodare il lavoro che richiede molta CPU. Serve per accodare il lavoro associato a I / O. E se si desidera eseguire operazioni di I / O, è necessario utilizzare un thread I / O (porta di completamento I / O).
In particolare, dovresti usare i callback asincroni supportati da qualunque classe di libreria stai usando. Questi metodi sono sempre etichettati molto chiaramente; iniziano con le parole Begin
e End
. Come in Stream.BeginRead
, Socket.BeginConnect
, WebRequest.BeginGetResponse
, e così via.
Questi metodi fanno utilizzare la ThreadPool
, ma usano IOCPs, che non non interferiscono con le richieste ASP.NET. Sono un tipo speciale di thread leggero che può essere "svegliato" da un segnale di interruzione dal sistema I / O. E in un'applicazione ASP.NET, normalmente hai un thread I / O per ogni thread di lavoro, quindi ogni singola richiesta può avere un'operazione asincrona accodata. Sono letteralmente centinaia di operazioni asincrone senza alcun calo significativo delle prestazioni (supponendo che il sottosistema di I / O possa tenere il passo). È molto più di quanto avrai mai bisogno.
Tieni presente che i delegati asincroni non funzionano in questo modo: finiranno per utilizzare un thread di lavoro, proprio come ThreadPool.QueueUserWorkItem
. Sono solo i metodi asincroni incorporati delle classi della libreria .NET Framework che sono in grado di farlo. Puoi farlo da solo, ma è complicato e un po 'pericoloso e probabilmente oltre lo scopo di questa discussione.
La migliore risposta a questa domanda, a mio parere, è non utilizzare ThreadPool
oThread
un'istanza in background in ASP.NET . Non è affatto come avviare un thread in un'applicazione Windows Form, dove lo fai per mantenere reattiva l'interfaccia utente e non ti interessa quanto sia efficiente. In ASP.NET, la tua preoccupazione è la velocità effettiva e tutto quel contesto che passa su tutti quei thread di lavoro ucciderà assolutamente la velocità effettiva, indipendentemente dal fatto che utilizzi ThreadPool
o meno.
Per favore, se ti ritrovi a scrivere codice di threading in ASP.NET, considera se potrebbe essere riscritto o meno per utilizzare metodi asincroni preesistenti e, se non è possibile, considera se hai davvero bisogno del codice per essere eseguito in un thread in background. Nella maggior parte dei casi, probabilmente aggiungerai complessità senza alcun vantaggio netto.