Creare variabili locali al thread con il .NET Framework 4.0
di Cristian Civera, in .NET Framework,
Il multithreading e la parallelizzazione sono tematiche che sono state prese molto in considerazione con il .NET Framework 4.0. Oltre al Parallel Framework, vi sono molti ritocchi e nuove funzionalità che già si è avuto modo di vedere con altri script. Una delle esigenze più comuni di cui si necessita quando si lavora con più thread è di mantenere dei valori di una stessa variabile a livello di thread, in modo che ogni thread lavori con oggetti diversi e possa manipolare la variabile come vuole.
Per raggiungere tale risultato, fin dalle prime versioni è possibile utilizzare l'attributo ThreadStatic sul membro della classe. Nel seguente esempio si suppone di eseguire un'azione parallelamente su più per thread, per far scrivere a video l'ID del thread che lo sta eseguendo, assicurandosi che tale valore venga inizializzato una sola volta per thread.
[ThreadStatic()] private static int threadId; static void Main(string[] args) { Action<int> a = i => { if (threadId == 0) threadId = Thread.CurrentThread.ManagedThreadId; Console.WriteLine("Iteration {0} on thread {1}", i, threadId); }; Parallel.For(1, 10, new ParallelOptions(), a); }
Eseguendolo, poiché i core sono due, alcuni thread verranno usati più di una volta e a video verrà stampato il seguente testo.
Iteration 1 on thread 1 Iteration 2 on thread 1 Iteration 3 on thread 1 Iteration 4 on thread 1 Iteration 6 on thread 1 Iteration 7 on thread 1 Iteration 8 on thread 1 Iteration 5 on thread 4 Iteration 9 on thread 3
Lo snippet precedente presenta però alcuni difetti. Prima di tutto si è obbligati a ricorrere ad una classe e ad un campo per poter memorizzare il valore per thread. Inoltre, ad ogni iterazione si è obbligati a controllare che la variabile sia inizializzata e provvedere a farlo qualora sia null o corrisponda ad una costante (in questo caso zero dell'intero). Non vi è altro modo poiché usando l'attributo ThreadStatic non è possibile utilizzare l'inizializzazione inline della variabile:
private static int threadId = Thread.CurrentThread.ManagedThreadId;
Sebbene non comporti alcun errore, il costruttore statico della classe viene eseguito solo una volta e la variabile threadId verrà inizializzata una sola volta.
Per superare questi problemi viene in aiuto la nuova classe ThreadLocal
// Variabile locale per thread using (ThreadLocal<Int32> threadIdLocal = new ThreadLocal<int>(() => Thread.CurrentThread.ManagedThreadId)) { //Interrogo direttamente la proprietà Value Action<int> a = i => Console.WriteLine("Iteration {0} on thread {1}", i, threadIdLocal.Value); Parallel.For(1, 10, new ParallelOptions(), a); }
Il codice diventa più compatto, più facile da usare ed inoltre è molto performante. La classe ThreadLocal

Commenti (
piace a
non piace a



