Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
La System.Threading.ThreadPool classe fornisce all'applicazione un pool di thread di lavoro gestiti dal sistema, consentendo di concentrarsi sulle attività dell'applicazione anziché sulla gestione dei thread. Se sono presenti attività brevi che richiedono l'elaborazione in background, il pool di thread gestiti è un modo semplice per sfruttare i vantaggi di più thread. L'utilizzo del pool di thread è notevolmente più semplice nel Framework 4 e nelle versioni successive, poiché è possibile creare oggetti Task e Task<TResult> che eseguono attività asincrone nei thread del pool di thread.
.NET usa thread dal pool di thread per molti scopi, tra cui operazioni TPL (Task Parallel Library), completamento di I/O asincrono, callback timer, operazioni di attesa registrate, chiamate di metodi asincrone tramite delegati e System.Net connessioni socket.
Caratteristiche del pool di thread
I thread del pool sono thread in background. Ogni thread utilizza la dimensione dello stack predefinita, viene eseguito con la priorità predefinita e si trova nell'ambiente multithreading. Quando un thread nel pool di thread completa l'attività, viene restituito a una coda di thread in attesa. Da questo momento può essere riutilizzato. Questo riutilizzo consente alle applicazioni di evitare il costo della creazione di un nuovo thread per ogni attività.
Esiste un solo pool di thread per processo.
Eccezioni nel pool di thread
Le eccezioni non gestite nei thread del pool terminano il processo. Esistono tre eccezioni a questa regola:
- Viene lanciato un System.Threading.ThreadAbortException in un thread del pool di thread perché è stato chiamato Thread.Abort.
- Un'eccezione System.AppDomainUnloadedException viene generata in un thread del pool di thread poiché il dominio dell'applicazione viene scaricato.
- Il Common Language Runtime o un processo host termina il thread.
Per altre informazioni, vedere Eccezioni nei thread gestiti.
Numero massimo di thread del pool thread
Il numero di operazioni che è possibile accodare al pool di thread è limitato solo dalla memoria disponibile. Tuttavia, il pool di thread limita simultaneamente il numero di thread che possono essere attivi nel processo. Se tutti i thread del pool di thread sono occupati, gli elementi di lavoro aggiuntivi vengono accodati fino a quando i thread per eseguirli non diventano disponibili. Le dimensioni predefinite del pool di thread per un processo dipendono da diversi fattori, ad esempio le dimensioni dello spazio indirizzi virtuale. Un processo può chiamare il ThreadPool.GetMaxThreads metodo per determinare il numero di thread.
È possibile controllare il numero massimo di thread usando i ThreadPool.GetMaxThreads metodi e ThreadPool.SetMaxThreads .
Annotazioni
Il codice che ospita Common Language Runtime può impostare le dimensioni usando il ICorThreadpool::CorSetMaxThreads metodo .
Minimi del pool di thread
Il pool di thread fornisce nuovi thread di lavoro o thread di completamento di I/O su richiesta finché non raggiunge un minimo specificato per ogni categoria. È possibile usare il ThreadPool.GetMinThreads metodo per ottenere questi valori minimi.
Annotazioni
Quando la domanda è bassa, il numero effettivo di thread del pool può scendere sotto i valori minimi.
Quando viene raggiunto un minimo, il pool di thread può creare thread aggiuntivi o attendere il completamento di alcune attività. Il pool di thread crea e distrugge i thread di lavoro per ottimizzare il throughput, definito come il numero di attività completate per unità di tempo. Un numero eccessivo di thread potrebbe non usare in modo ottimale le risorse disponibili, mentre un numero eccessivo di thread potrebbe aumentare la contesa delle risorse.
Attenzione
È possibile usare il ThreadPool.SetMinThreads metodo per aumentare il numero minimo di thread inattivi. Tuttavia, l'aumento inutilmente di questi valori può causare problemi di prestazioni. Se troppe attività iniziano contemporaneamente, tutte potrebbero sembrare lente. Nella maggior parte dei casi il pool di thread avrà prestazioni migliori con il proprio algoritmo per l'allocazione dei thread.
Uso del pool di thread
Il modo più semplice per usare il pool di thread consiste nell'usare Task Parallel Library (TPL). Per impostazione predefinita, i tipi TPL come Task e Task<TResult> usano thread del pool per eseguire attività.
È anche possibile usare il pool di thread chiamando ThreadPool.QueueUserWorkItem dal codice gestito (o ICorThreadpool::CorQueueUserWorkItem dal codice non gestito) e passando un System.Threading.WaitCallback delegato che rappresenta il metodo che esegue l'attività.
Un altro modo per usare il pool di thread consiste nell'accodare elementi di lavoro correlati a un'operazione di attesa usando il metodo ThreadPool.RegisterWaitForSingleObject e passando un oggetto System.Threading.WaitHandle che, quando viene segnalato o scade il timeout, chiama il metodo rappresentato dal delegato System.Threading.WaitOrTimerCallback. I thread del pool di thread vengono usati per invocare i metodi di callback.
Per gli esempi, controllare le pagine API di riferimento.
Ignorare i controlli di sicurezza
Il pool di thread fornisce anche i metodi ThreadPool.UnsafeQueueUserWorkItem e ThreadPool.UnsafeRegisterWaitForSingleObject. Usare questi metodi solo quando si è certi che lo stack del chiamante è irrilevante rispetto ad eventuali verifiche di sicurezza effettuate durante l'esecuzione del compito in coda. ThreadPool.QueueUserWorkItem e ThreadPool.RegisterWaitForSingleObject acquisiscono entrambi lo stack del chiamante, che viene unito nello stack del thread del pool di thread quando il thread inizia a eseguire un'attività. Se è necessario un controllo di sicurezza, è necessario controllare l'intero stack. Anche se il controllo garantisce la sicurezza, ha anche un costo delle prestazioni.
Quando non usare i thread del thread pool
Esistono diversi scenari in cui è opportuno creare e gestire thread personalizzati anziché usare thread del pool di thread:
- È necessario un thread in primo piano.
- È necessario che un thread abbia una priorità specifica.
- Sono presenti attività che causano il blocco del thread per lunghi periodi di tempo. Il pool di thread ha un numero massimo di thread, pertanto un numero elevato di thread bloccati potrebbe impedire l'avvio delle attività.
- È necessario posizionare i thread in un apartment a thread singolo. Tutti i ThreadPool thread si trovano nell'apartment multithreading.
- È necessario avere un'identità stabile associata al thread o dedicare un thread a un'attività.