2013-08-20 10 views
61

[ThreadStatic] viene 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 degli attributi over generici in questo caso?ThreadStatic v.s. ThreadLocal <T>: è generico migliore dell'attributo?

+4

Vedere http://reedcopsey.com/2009/11/12/thread-specific-data-becomes-easier-in-net-4-0-via-threadlocalt/ - Non vedo cosa questo debba fare con riflessione però ... –

risposta

72

Qualcosa che il post del blog ha annotato nei commenti non rende esplicito, ma trovo che sia molto importante, è che [ThreadStatic] non inizializza automaticamente le cose per ogni thread. Per esempio, supponiamo di avere questo:

[ThreadStatic] 
private static int Foo = 42; 

Il primo thread che utilizza questo vedrà Foo inizializzato a 42. Ma i fili 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 questo problema consentendo di fornire una funzione di inizializzazione (come mostra il blog di Reed) che viene eseguita prima della prima volta che si accede all'elemento.

A mio parere, non è vantaggioso utilizzare [ThreadStatic] anziché ThreadLocal<T>.

+10

Tranne forse che ['ThreadLocal '] (http://msdn.microsoft.com/en-us/library/dd642243 (v = vs.110) .aspx) è disponibile in .NET. 4 e versioni successive e [l'attributo 'ThreadStatic'] (http://msdn.microsoft.com/en-us/library/system.threadstaticattribute (v = vs.100) .aspx) è disponibile anche in 3.5 e sotto. – Jeroen

+0

E se non si stanno utilizzando gli inizializzatori per impostare il valore, ma lo si sta invece impostando in un secondo momento dopo l'inizializzazione, l'uso di [ThreadStatic] è sintatticamente più pulito. – Thought

+0

'[ThreadStatic]' ha il vantaggio di non dover modificare i riferimenti esistenti a quel campo nel codice. – NextInLine

23

ThreadStatic Inizializza solo sul primo thread, ThreadLocal Initialize per ogni thread. Sotto è la dimostrazione semplice:

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(); 
    } 

enter image description here

+2

Interessante esempio, ma ho la deriva. – Eniola

7

L'idea principale dietro ThreadStatic è quello di mantenere una copia separata della variabile per ciascun 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(); 
     } 
    } 

del frammento precedente, abbiamo una copia separata di value per ciascun filo, compreso il filo principale.

enter image description here

Quindi, una variabile ThreadStatic viene inizializzato al valore predefinito su altri thread tranne il filo su cui viene creato.

Se vogliamo inizializzare la variabile su ciascun thread a modo nostro, utilizzare ThreadLocal.

+0

E l'articolo completo può essere trovato [qui] (http://putridparrot.com/blog/using-threadstatic-and-threadlocal/). – dee