[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à Fooinizializzato 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' ThreadStaticattributo è disponibile anche in 3.5 e versioni precedenti.
ThreadLocal<T>implementa IDisposablee di solito ti costringe a implementare IDisposableanche tu , il che costringe i tuoi chiamanti a sbarazzarti e quindi implementare IDisposableanche tu ...
ThreadLocalo ThreadStaticcon 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 valueper 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.