2011-03-08 8 views
105

¿Cómo funciona el atributo [ThreadStatic]? Supuse que el compilador emitiría alguna IL para rellenar/recuperar el valor en el TLS, pero al mirar un desmontaje parece que no lo hace a ese nivel.¿Cómo funciona el atributo ThreadStatic?

Como seguimiento, ¿qué sucede si lo pones en un miembro no estático? Tuvimos un desarrollador que cometió ese error y el compilador ni siquiera ofrece una advertencia.

actualización

Segunda pregunta respondida aquí: ThreadStatic Modified with Static C#

+1

Si el IL generado es el mismo (que de hecho lo es), el tiempo de ejecución debe codificarse específicamente para saber cómo asignar y leer el valor cuando llega a dicho campo decorado. Parece un truco :) –

Respuesta

75

La semántica de implementación de subprocesos estáticos está por debajo del nivel IL, en el compilador .NET jit. Los compiladores que emiten a IL como VB.NET y C# no necesitan saber nada sobre Win32 TLS para emitir código IL que pueda leer y escribir una variable que tenga el atributo ThreadStatic. No hay nada especial acerca de la variable en lo que C# conoce: es solo un lugar para leer y escribir cosas. El hecho de que tenga un atributo no tiene ninguna consecuencia para C#. C# solo necesita saber para emitir instrucciones de lectura o escritura de IL para ese nombre de símbolo.

La 'carga pesada' es realizada por el núcleo CLR que es responsable de hacer que IL funcione en una arquitectura de hardware particular.

Eso también explicaría por qué poner el atributo en un símbolo inapropiado (no estático) no obtiene una reacción del compilador. El compilador no sabe qué semántica especial requiere el atributo. Las herramientas de análisis de código como FX/Cop, sin embargo, deberían saberlo.

Otra forma de verlo: CIL define un conjunto de ámbitos de almacenamiento: almacenamiento estático (global), almacenamiento de miembros y almacenamiento de pila. TLS no está en esa lista, muy probablemente porque TLS no necesita estar en esa lista. Si las instrucciones de lectura y escritura de IL son suficientes para acceder a TLS cuando el símbolo está etiquetado con un atributo TLS, ¿por qué IL debe tener alguna representación o tratamiento especial para TLS? No es necesario.

97

¿Cómo [ThreadStatic] atribuyen trabajo?

Puede pensar que el campo marcado con ThreadStatic está conectado a una rosca y su vida útil es comparable a la vida útil de una rosca.

Así que en pseudocódigo ThreadStatic es similar (la semántica) para tener una clave-valor que se asigna a un hilo:

Thread.Current["MyClass.myVariable"] = 1; 
Thread.Current["MyClass.myvariable"] += 1; 

pero la sintaxis es un poco más fácil:

class MyClass { 
    [ThreadStatic] 
    static int myVariable; 
} 
// .. then 
MyClass.myVariable = 1; 
MyClass.myVariable += 1; 

¿Qué pasa si lo pones en un miembro no estático?

Creo que es ignorado:

class A { 
     [ThreadStatic] 
     public int a; 
    } 
    [Test] 
    public void Try() { 
     var a1 = new A(); 
     var a2 = new A(); 
     a1.a = 5; 
     a2.a = 10; 
     a1.a.Should().Be.EqualTo(5); 
     a2.a.Should().Be.EqualTo(10); 
    } 

Además, es importante mencionar que ThreadStatic no requiere ningún mecanismo de sincronización, en comparación con los campos estáticos normales (porque el estado no es compartida).

+1

Segundo como pseudo código debe ser '" MyClass.myVariable "', ¿no? – akshay2000

+0

No estoy seguro de las restricciones exactas, pero solo quería señalar si no es obvio que no tiene que ser un tipo primitivo. Si nos fijamos en el origen de 'TransactionScope' almacenan todo tipo de cosas para el alcance (https://referencesource.microsoft.com/#System.Transactions/System/Transactions/Transaction.cs,0e19ea1e3a994306) –

Cuestiones relacionadas