2011-10-21 17 views
11

Ho una libreria molto vecchia ma molto grande che sto considerando di convertire in una libreria di classi C#. La libreria esistente utilizza molte variabili globali memorizzate nel TLS. C# non ha un concetto reale di variabili globali, ma una soluzione alternativa è usare una classe statica chiamata qualcosa come GlobalVar e metterle tutte in questa classe in modo che possano essere accessibili via GlobalVar.xxxxxxArchiviazione locale di thread per la libreria di classi C#

Tuttavia, il mio pensiero è che questo si spezzerà tutto il codice esistente che viene convertito come classe GlobalVar sarà una normale classe globale e non per l'archiviazione di thread. C'è un modo per ottenere questi globals per thread? vale a dire qual è l'equivalente di __declspec (thread) statico in C#?

Dovrei aggiungere a questo punto che odio le variabili globali. Penso che siano spesso il risultato di un design scadente. Tuttavia, a causa delle ristrette restrizioni temporali, la prima fase consiste nel convertire la libreria in C# con il minimo sforzo e quindi la fase 2 sarà la riprogettazione corretta.

risposta

14

Ci sono la classe ThreadLocal (introdotta in 4.0) e la ThreadStaticAttribute.

Il ThreadStaticAttribute può essere utilizzato solo sui campi static. La classe ThreadLocal può essere utilizzata su campi "normali" ma è più lenta.

Si noti che se non si controlla il thread in cui ci si trova (ad esempio, si è una pagina di ASP.NET e si avvia su un thread pre-usato "casuale", oppure si è un thread di un ThreadPool), quindi le variabili "thread-static" (in generale, non l'attributo) verranno preinizializzate con i vecchi valori del thread precedente. (vedi ad esempio A tale of two techniques: The [ThreadStatic] Attribute and System.Web.HttpContext.Current.Items)

Mi stavo dimenticando, c'è lo Thread.AllocateDataSlot che ha simili "obiettivi" rispetto agli altri.

+0

Hehe, sembra insistere nell'insegnarci la lingua italiana :-) –

+0

@xanatos 'Il ThreadStaticAttribute può essere utilizzato solo su campi statici' non è sempre vero. Le persone potrebbero voler dichiarare una variabile per-thread per istanza –

+0

Il mio italiano non è eccezionale ma scherza a parte, molte grazie per l'aiuto. Anche se sono un po 'preoccupato per l'ultimo paragrafo che riguarda l'uso di un ThreadPool. Non penso che questo sarà un problema all'inizio, ma è qualcosa che potrebbe essere necessario prendere in considerazione in futuro. – Jonnster

3

È possibile ottenere la stessa archiviazione locale del thread utilizzando l'attributo [ThreadStatic] o. Net 4 utilizzando la classe ThreadLocal.

[ThreadStatic]  
private static string MyThreadGlobal; 

private ThreadLocal<string> MyThreadGlobal = new ThreadLocal<string>(); 

C'è anche la classe CallContext ma gli altri approcci sono probabilmente preferito.

3

Presumendo che si vuole utilizzare NET 4.0, si potrebbe avere un static ThreadLocal<ThreadLocalData> in cui la classe ThreadLocalData ha tutte le variabili come proprietà:

class ThreadLocalData 
{ 
    public int GlobalInt { get; set; } 
    public string GlobalString { get; set; } 
} 

class Global 
{ 
    static ThreadLocal<ThreadLocalData> _ThreadLocal = 
     new ThreadLocal<ThreadLocalData>(() => new ThreadLocalData()); 

    public static ThreadLocalData ThreadLocal 
    { 
     get { return _ThreadLocal.Value; } 
    } 
} 

Si potrebbe quindi accedere alle proprietà in questo modo:

int i = Global.ThreadLocal.GlobalInt; 

È possibile aggiungere qualsiasi variabile globale che non sia thread-local come proprietà normali della classe Global.

Problemi correlati