[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?
c#
generics
attributes
thread-local
threadstatic
user2341923
źródło
źródło
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
zainicjowany42
. 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]
zamiastThreadLocal<T>
.źródło
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żaIDisposable
i zwykle zmusza cię do implementacjiIDisposable
, co zmusza twoich rozmówców do pozbycia się ciebie, a zatem również implementacjiIDisposable
...ThreadLocal
lubThreadStatic
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(); }
źródło
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.
źródło