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

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

  • Use campos estáticos relativos a threads (campos relativos Shared a threads no Visual Basic) se você puder antecipar 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 em tempo de compilação.

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

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

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

Exclusividade dos dados no TLS gerenciado

Quer você use campos estáticos relativos a threads ou slots de dados, os dados no TLS gerenciado são exclusivos para a combinação de thread e domínio de aplicativo.

  • Dentro de 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 de aplicativo.

Por exemplo, se um thread define o valor de um campo estático relativo ao thread, entra em outro domínio de aplicativo e, em seguida, recupera o valor do campo, o valor recuperado no segundo domínio de aplicativo difere do valor no primeiro domínio de aplicativo. A definição de 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 de aplicativo permanecem independentes dos dados no segundo domínio de aplicativo.

Campos estáticos relativos a threads

Se você souber que uma parte dos dados é sempre exclusiva para uma combinação de thread e domínio de aplicativo, aplique o ThreadStaticAttribute atributo ao campo estático. Use o campo como faria com qualquer outro campo estático. Os dados no campo são exclusivos para cada thread que o utiliza.

Os campos estáticos relativos a threads fornecem melhor desempenho do que os slots de dados e têm o benefício da verificação de tipo em 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 de 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 confiar em construtores de classe para inicializar campos estáticos relativos a threads. Em vez disso, evite inicializar campos estáticos relativos a threads e assuma que eles são inicializados para null (Nothing) ou para seus valores padrão.

Slots de dados

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

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

Slots nomeados podem ser convenientes, porque você pode recuperar o slot quando precisar dele passando seu nome para o GetNamedDataSlot método, em vez de manter uma referência a um slot sem nome. No entanto, se outro componente usar o mesmo nome para seu armazenamento relativo ao thread e um thread executar código do componente e do outro componente, os dois componentes poderão corromper os dados um do outro. (Este cenário pressupõe que ambos os componentes estão sendo executados no mesmo domínio de aplicativo e que eles não foram projetados para compartilhar os mesmos dados.)

Consulte também