[ThreadStatic]
é definido usando atributo enquanto ThreadLocal<T>
usa genérico. Por que diferentes soluções de design foram escolhidas? Quais são as vantagens e desvantagens de usar atributos genéricos em vez de atributos neste caso?
[ThreadStatic]
é definido usando atributo enquanto ThreadLocal<T>
usa genérico. Por que diferentes soluções de design foram escolhidas? Quais são as vantagens e desvantagens de usar atributos genéricos em vez de atributos neste caso?
Respostas:
Algo que o post do blog anotado nos comentários não deixa explícito, mas acho muito importante, é que [ThreadStatic]
não inicializa as coisas automaticamente para cada tópico. Por exemplo, digamos que você tenha este:
[ThreadStatic]
private static int Foo = 42;
O primeiro thread que usar isso será Foo
inicializado como 42
. Mas os tópicos subsequentes não. O inicializador funciona apenas para o primeiro thread. Então você acaba tendo que escrever código para verificar se ele foi inicializado.
ThreadLocal<T>
resolve esse problema permitindo que você forneça uma função de inicialização (como mostra o blog de Reed) que é executada antes da primeira vez que o item é acessado.
Em minha opinião, não há vantagem em usar em [ThreadStatic]
vez de ThreadLocal<T>
.
ThreadLocal<T>
esteja disponível no .NET 4 e superior, e o ThreadStatic
atributo também está disponível no 3.5 e abaixo.
ThreadLocal<T>
implementa IDisposable
e geralmente força você a implementar IDisposable
também, o que força seus chamadores a descartá-lo e, portanto, implementar IDisposable
também ...
ThreadLocal
ou ThreadStatic
com threads de pool. Esses valores permanecerão por toda a vida útil do thread do pool, não apenas para a tarefa que você atribui. Isso pode causar problemas de maneiras nada óbvias. Consulte stackoverflow.com/questions/561518/… e perguntas semelhantes para obter mais informações.
static
? Consulte msdn.microsoft.com/en-us/library/…
ThreadStatic Initialize apenas no primeiro thread, ThreadLocal Initialize para cada thread. Abaixo está a demonstração simples:
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();
}
A ideia principal por trás do ThreadStatic é manter uma cópia separada da variável para cada 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();
}
}
No snippet acima, temos uma cópia separada de value
para cada tópico, incluindo o tópico principal.
Portanto, uma variável ThreadStatic será inicializada com seu valor padrão em outras threads, exceto na thread em que foi criada.
Se quisermos inicializar a variável em cada thread à nossa maneira, use ThreadLocal.