[ThreadStatic]
wird mit Attribut definiert, während ThreadLocal<T>
generisch verwendet wird. Warum wurden unterschiedliche Designlösungen gewählt? Welche Vor- und Nachteile hat die Verwendung von generischen Überattributen in diesem Fall?
[ThreadStatic]
wird mit Attribut definiert, während ThreadLocal<T>
generisch verwendet wird. Warum wurden unterschiedliche Designlösungen gewählt? Welche Vor- und Nachteile hat die Verwendung von generischen Überattributen in diesem Fall?
Antworten:
Etwas, das der Blog-Beitrag in den Kommentaren nicht explizit macht, aber ich finde es sehr wichtig, dass [ThreadStatic]
es nicht automatisch Dinge für jeden Thread initialisiert. Angenommen, Sie haben Folgendes:
[ThreadStatic]
private static int Foo = 42;
Der erste Thread, der dies verwendet, wird auf Foo
initialisiert 42
. Aber nachfolgende Threads werden nicht. Der Initialisierer funktioniert nur für den ersten Thread. Am Ende müssen Sie also Code schreiben, um zu überprüfen, ob er initialisiert ist.
ThreadLocal<T>
Behebt dieses Problem, indem Sie eine Initialisierungsfunktion (wie Reeds Blog zeigt) bereitstellen, die vor dem ersten Zugriff auf das Element ausgeführt wird.
Meiner Meinung nach hat die Verwendung von [ThreadStatic]
statt keinen Vorteil ThreadLocal<T>
.
ThreadLocal<T>
ist dies in .NET 4 und höher verfügbar, und das ThreadStatic
Attribut ist auch in Version 3.5 und darunter verfügbar.
ThreadLocal<T>
implementiert IDisposable
und zwingt Sie normalerweise auch zur Implementierung IDisposable
, was Ihre Anrufer dazu zwingt, Sie zu entsorgen und daher auch zu implementieren IDisposable
...
ThreadLocal
oder ThreadStatic
mit Pool-Threads sein. Diese Werte bleiben während der gesamten Lebensdauer des Pool-Threads erhalten, nicht nur für die Aufgabe, die Sie ihm zuweisen. Das kann Ihnen auf ziemlich nicht offensichtliche Weise Probleme bereiten. Weitere Informationen finden Sie unter stackoverflow.com/questions/561518/… und ähnlichen Fragen.
static
? Siehe msdn.microsoft.com/en-us/library/…
ThreadStatic Initialize nur für den ersten Thread, ThreadLocal Initialize für jeden Thread. Unten ist die einfache Demonstration:
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();
}
Die Hauptidee hinter ThreadStatic besteht darin, für jeden Thread eine separate Kopie der Variablen zu verwalten .
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();
}
}
Im obigen Snippet haben wir value
für jeden Thread eine separate Kopie , einschließlich des Hauptthreads.
Daher wird eine ThreadStatic-Variable in anderen Threads mit Ausnahme des Threads, in dem sie erstellt wurde, auf ihren Standardwert initialisiert.
Wenn wir die Variable für jeden Thread auf unsere eigene Weise initialisieren möchten, verwenden Sie ThreadLocal.