[ThreadStatic]
jest definiowany przy użyciu atrybutu, podczas gdy ThreadLocal<T>
używa generic. Dlaczego wybrano różne rozwiązania projektowe? Jakie są zalety i wady używania atrybutów ogólnych zamiast atrybutów w tym przypadku?
[ThreadStatic]
jest definiowany przy użyciu atrybutu, podczas gdy ThreadLocal<T>
używa generic. Dlaczego wybrano różne rozwiązania projektowe? Jakie są zalety i wady używania atrybutów ogólnych zamiast atrybutów w tym przypadku?
Odpowiedzi:
Coś, co we wpisie na blogu odnotowano w komentarzach, nie jest jednoznaczne, ale uważam za bardzo ważne, to to, że [ThreadStatic]
nie inicjuje automatycznie rzeczy dla każdego wątku. Na przykład powiedz, że masz to:
[ThreadStatic]
private static int Foo = 42;
Pierwszy wątek, który to używa, zostanie Foo
zainicjowany 42
. Ale kolejne wątki już nie. Inicjator działa tylko dla pierwszego wątku. W końcu musisz napisać kod, aby sprawdzić, czy jest zainicjowany.
ThreadLocal<T>
rozwiązuje ten problem, pozwalając ci podać funkcję inicjalizacyjną (jak pokazuje blog Reeda), która jest uruchamiana przed pierwszym dostępem do elementu.
Moim zdaniem nie ma żadnej korzyści z używania [ThreadStatic]
zamiast ThreadLocal<T>
.
ThreadLocal<T>
jest dostępny w .NET 4 iw górę, a atrybut dostępny w 3,5 i poniżej jest również. ThreadStatic
ThreadLocal<T>
wdraża IDisposable
i zwykle zmusza cię do implementacji IDisposable
, co zmusza twoich rozmówców do pozbycia się ciebie, a zatem również implementacji IDisposable
...
ThreadLocal
lub ThreadStatic
z wątkami puli. Te wartości pozostaną przez cały czas życia wątku puli, a nie tylko dla zadania, które mu przydzielisz. Może to powodować kłopoty na dość nieoczywiste sposoby. Aby uzyskać więcej informacji, zobacz stackoverflow.com/questions/561518/ ... i podobne pytania.
static
? Zobacz msdn.microsoft.com/en-us/library/…
ThreadStatic Zainicjuj tylko w pierwszym wątku, ThreadLocal Zainicjuj dla każdego wątku. Poniżej znajduje się prosta demonstracja:
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();
}
Główną ideą stojącą za ThreadStatic jest utrzymywanie oddzielnej kopii zmiennej dla każdego wątku .
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();
}
}
W powyższym fragmencie mamy oddzielną kopię value
dla każdego wątku, w tym wątku głównego.
Tak więc zmienna ThreadStatic zostanie zainicjowana do wartości domyślnej w innych wątkach, z wyjątkiem wątku, w którym została utworzona.
Jeśli chcemy zainicjować zmienną w każdym wątku na swój własny sposób, użyj ThreadLocal.