[ThreadStatic]
è definito utilizzando l'attributo mentre ThreadLocal<T>
utilizza generico. Perché sono state scelte diverse soluzioni di design? Quali sono i vantaggi e gli svantaggi dell'utilizzo di attributi generici rispetto in questo caso?
[ThreadStatic]
è definito utilizzando l'attributo mentre ThreadLocal<T>
utilizza generico. Perché sono state scelte diverse soluzioni di design? Quali sono i vantaggi e gli svantaggi dell'utilizzo di attributi generici rispetto in questo caso?
Risposte:
Qualcosa che il post del blog annotato nei commenti non rende esplicito, ma trovo che sia molto importante, è che [ThreadStatic]
non inizializza automaticamente le cose per ogni thread. Ad esempio, supponi di avere questo:
[ThreadStatic]
private static int Foo = 42;
Il primo thread che utilizza questo verrà Foo
inizializzato a 42
. Ma i thread successivi non lo faranno. L'inizializzatore funziona solo per il primo thread. Quindi finisci per dover scrivere codice per verificare se è inizializzato.
ThreadLocal<T>
risolve il problema consentendo di fornire una funzione di inizializzazione (come mostra il blog di Reed) che viene eseguita prima del primo accesso all'elemento.
A mio parere, non vi è alcun vantaggio nell'usare al [ThreadStatic]
posto di ThreadLocal<T>
.
ThreadLocal<T>
è disponibile in .NET 4 e versioni successive e l' ThreadStatic
attributo è disponibile anche in 3.5 e versioni precedenti.
ThreadLocal<T>
implementa IDisposable
e di solito ti costringe a implementare IDisposable
anche tu , il che costringe i tuoi chiamanti a sbarazzarti e quindi implementare IDisposable
anche tu ...
ThreadLocal
o ThreadStatic
con i thread del pool. Questi valori rimarranno per l'intera durata del thread del pool, non solo per l'attività assegnata. Ciò può causare problemi in modi piuttosto non ovvi. Vedi stackoverflow.com/questions/561518/… e domande simili per maggiori informazioni.
static
? Vedere msdn.microsoft.com/en-us/library/...
ThreadStatic Initialize solo sul primo thread, ThreadLocal Initialize per ogni thread. Di seguito la semplice dimostrazione:
public static ThreadLocal<int> _threadlocal =
new ThreadLocal<int>(() =>
{
return Thread.CurrentThread.ManagedThreadId;
});
public static void Main()
{
new Thread(() =>
{
for (int x = 0; x < _threadlocal.Value; x++)
{
Console.WriteLine("First Thread: {0}", x);
}
}).Start();
new Thread(() =>
{
for (int x = 0; x < _threadlocal.Value; x++)
{
Console.WriteLine("Second Thread: {0}", x);
}
}).Start();
Console.ReadKey();
}
L'idea principale alla base di ThreadStatic è mantenere una copia separata della variabile per ogni thread .
class Program
{
[ThreadStatic]
static int value = 10;
static void Main(string[] args)
{
value = 25;
Task t1 = Task.Run(() =>
{
value++;
Console.WriteLine("T1: " + value);
});
Task t2 = Task.Run(() =>
{
value++;
Console.WriteLine("T2: " + value);
});
Task t3 = Task.Run(() =>
{
value++;
Console.WriteLine("T3: " + value);
});
Console.WriteLine("Main Thread : " + value);
Task.WaitAll(t1, t2, t3);
Console.ReadKey();
}
}
Nello snippet sopra, abbiamo una copia separata di value
per ogni thread, incluso il thread principale.
Quindi, una variabile ThreadStatic verrà inizializzata al suo valore predefinito su altri thread eccetto il thread su cui è stata creata.
Se vogliamo inizializzare la variabile su ogni thread a modo nostro, usa ThreadLocal.