Compartilhar via


Armazenamento local de thread: Campos estáticos relativos a thread e slots de dados

Você pode usar o TLS (armazenamento local de thread gerenciado) para armazenar dados exclusivos para um thread e um domínio de aplicativo. O .NET fornece duas maneiras de usar o TLS gerenciado: campos estáticos relativos ao thread e slots de dados.

  • Use campos estáticos relativos a thread (campos Shared relativos a thread no Visual Basic) se você puder prever suas necessidades exatas em tempo de compilação. Os campos estáticos relativos ao thread fornecem o melhor desempenho. Eles também oferecem os benefícios da verificação de tipo durante a compilação.

  • Use slots de dados quando seus requisitos reais só puderem ser descobertos em tempo de execução. Os slots de dados são mais lentos e mais estranhos de usar do que os campos estáticos relativos ao thread e os dados são armazenados como tipo Object, portanto, você deve convertê-los no tipo correto antes de usá-los.

No C++não gerenciado, você usa TlsAlloc para alocar slots dinamicamente e __declspec(thread) declarar que uma variável deve ser alocada no armazenamento relativo ao thread. Os campos estáticos relativos ao thread e os slots de dados fornecem a versão gerenciada desse comportamento.

Você pode usar a System.Threading.ThreadLocal<T> classe para criar objetos locais de thread que são inicializados de forma preguiçosa quando o objeto é consumido pela primeira vez. Para obter mais informações, consulte Inicialização Lenta.

Exclusividade dos dados no TLS gerenciado

Não importa se você usa campos estáticos relativos a thread ou slots de dados, os dados em TLS gerenciado são exclusivos da combinação de thread e domínio de aplicativos.

  • Em um domínio de aplicativo, um thread não pode modificar dados de outro thread, mesmo quando ambos os threads usam o mesmo campo ou slot.

  • Quando um thread acessa o mesmo campo ou slot de vários domínios de aplicativo, um valor separado é mantido em cada domínio do aplicativo.

Por exemplo, se um thread define o valor de um campo estático relativo a thread, insere outro domínio de aplicativo e, em seguida, recupera o valor do campo, o valor recuperado no segundo domínio do aplicativo difere do valor no primeiro domínio do aplicativo. Definir um novo valor para o campo no segundo domínio do aplicativo não afeta o valor do campo no primeiro domínio do aplicativo.

Da mesma forma, quando um thread obtém o mesmo slot de dados nomeado em dois domínios de aplicativo diferentes, os dados no primeiro domínio do aplicativo permanecem independentes dos dados no segundo domínio do aplicativo.

Thread-Relative Campos Estáticos

Se você souber que um pedaço de dados é sempre exclusivo para uma combinação thread e application-domain, aplique o ThreadStaticAttribute atributo ao campo estático. Use o campo como você usaria qualquer outro campo estático. Os dados no campo são exclusivos para cada thread que os usa.

Campos estáticos relativos a thread fornecem melhor desempenho do que os slots de dados e têm o benefício da verificação do tipo de tempo de compilação.

Lembre-se de que qualquer código de construtor de classe será executado no primeiro thread no primeiro contexto que acessa o campo. Em todos os outros threads ou contextos no mesmo domínio do aplicativo, os campos serão inicializados para null (Nothing no Visual Basic) se forem tipos de referência, ou para seus valores padrão se forem tipos de valor. Portanto, você não deve depender de construtores de classe para inicializar campos estáticos relativos a threads. Em vez disso, evite inicializar campos estáticos relativos ao thread e suponha que eles sejam inicializados para null (Nothing) ou para seus valores padrão.

Slots de dados

O .NET fornece slots de dados dinâmicos exclusivos para uma combinação de thread e domínio de aplicativo. Há dois tipos de slots de dados: slots nomeados e slots sem nome. Ambos são implementados usando a LocalDataStoreSlot estrutura.

Para slots nomeados e sem nome, use os métodos Thread.SetData e Thread.GetData para definir e recuperar as informações no slot. Estes são métodos estáticos que sempre atuam nos dados do thread que os está executando no momento.

Os slots nomeados podem ser convenientes, pois você pode recuperar o slot quando precisar dele passando o nome dele para o método GetNamedDataSlot, em vez de manter uma referência a um slot sem nome. No entanto, se outro componente usa o mesmo nome para seu armazenamento relativo ao thread e um thread executa o código do seu componente e do outro componente, os dois componentes podem corromper os dados uns dos outros. (Esse cenário pressupõe que ambos os componentes estão em execução no mesmo domínio do aplicativo e que eles não foram projetados para compartilhar os mesmos dados.)

Consulte também