Almacenamiento local de subprocesos: Campos estáticos relacionados con subprocesos y ranuras de datos

Puede usar el almacenamiento local para el subproceso (TLS) administrado a fin de almacenar los datos que sean exclusivos de un subproceso y un dominio de la aplicación. .NET proporciona dos maneras de usar el TLS administrado: ranuras para datos y campos estáticos relacionados con subprocesos.

  • Use campos estáticos relacionados con subprocesos (campos Shared relacionados con subprocesos en Visual Basic) si puede anticipar las necesidades exactas en tiempo de compilación. Los campos estáticos relacionados con subprocesos proporcionan el mejor rendimiento. También proporcionan las ventajas de la comprobación de tipos en tiempo de compilación.

  • Use las ranuras de datos si se pueden detectar los requisitos reales solo en tiempo de ejecución. Las ranuras de datos son más lentas y más difíciles de usar que los campos estáticos relacionados con subprocesos, y los datos se almacenan como tipos Object, por lo que debe convertirlos al tipo correcto antes de utilizarlos.

En C++ no administrado, use TlsAlloc para asignar ranuras de forma dinámica y __declspec(thread) para declarar que una variable debería asignarse en el almacenamiento relacionado con los subprocesos. Los campos estáticos y las ranuras para datos relacionados con los subprocesos proporcionan la versión administrada de este comportamiento.

Puede usar la clase System.Threading.ThreadLocal<T> para crear objetos locales de subprocesos que se inicializan de forma diferida la primera vez que se usa el objeto. Para obtener más información, vea Inicialización diferida.

Unicidad de los datos en la TLS administrada

Si usa los campos estáticos o las ranuras para datos relacionados con subprocesos, los datos de la TLS administrada son exclusivos de la combinación de subproceso y dominio de aplicación.

  • Dentro de un dominio de aplicación, un subproceso no puede modificar datos de otro subproceso, aunque ambos subprocesos utilicen el mismo campo o ranura.

  • Cuando un subproceso accede al mismo campo o ranura desde varios dominios de aplicación, se mantiene un valor independiente en cada dominio de aplicación.

Por ejemplo, si un subproceso establece el valor de un campo estático relacionado con el subproceso, escribe otro dominio de aplicación y luego recupera el valor del campo, entonces el valor recuperado en el segundo dominio de aplicación difiere del valor del primer dominio de aplicación. Establecer un nuevo valor para el campo del segundo dominio de aplicación no influye en el valor del campo del primer dominio de aplicación.

De forma similar, si un subproceso obtiene la ranura para datos con el mismo nombre en dos dominios de aplicación distintos, los datos del primer dominio de aplicación son independientes de los datos del segundo dominio de aplicación.

Campos estáticos relacionados con subprocesos

Si sabe que un elemento de datos siempre es exclusivo para una combinación de dominio de aplicación y subproceso, aplique el atributo ThreadStaticAttribute al campo estático. Utilice el campo como utilizaría cualquier otro campo estático. Los datos del campo son exclusivos para cada subproceso que los use.

Los campos estáticos relacionados con subprocesos ofrecen mayor rendimiento que las ranuras para datos y, además, tienen la ventaja de la comprobación de tipos en tiempo de compilación.

Tenga en cuenta que cualquier código del constructor de clase se ejecutará en el primer subproceso del primer contexto que acceda al campo. En todos los demás subprocesos o contextos del mismo dominio de aplicación, los campos se inicializarán como null (Nothing en Visual Basic) si son tipos de referencia o como valores predeterminados si son tipos de valor. Por lo tanto, no debe basarse en los constructores de clase para inicializar campos estáticos relacionados con subprocesos. En su lugar, evite inicializar los campos estáticos relacionados con subprocesos y suponga que se han inicializado como null (Nothing) o con sus valores predeterminados.

Ranuras para datos

.NET proporciona ranuras para datos dinámicos exclusivas para la combinación de subproceso y dominio de la aplicación. Hay dos tipos de ranuras para datos: ranuras con nombre y ranuras sin nombre. Ambos tipos se implementan mediante la estructura LocalDataStoreSlot.

Para las ranuras con nombre y sin nombre, use los métodos Thread.SetData y Thread.GetData para establecer y recuperar la información en la ranura. Se trata de métodos estáticos que siempre actúan en los datos para el subproceso que los ejecuta actualmente.

Las ranuras con nombre pueden ser prácticas, porque puede recuperar la ranura cuando lo necesite pasando su nombre al método GetNamedDataSlot, en lugar de mantener una referencia a una ranura sin nombre. Sin embargo, si otro componente usa el mismo nombre para su almacenamiento relacionado con subprocesos y un subproceso ejecuta código desde el componente y el otro componente, los dos componentes podrían dañar los datos del otro. (En este escenario se supone que ambos componentes se ejecutan en el mismo dominio de aplicación y que no están diseñados para compartir los mismos datos).

Vea también