Compartilhar via


Threading gerenciado e não gerenciado no Windows

O gerenciamento de todos os threads é feito por meio da Thread classe, incluindo threads criados pelo common language runtime e aqueles criados fora do runtime que inserem o ambiente gerenciado para executar o código. O runtime monitora todos os threads em seu processo que já executaram código no ambiente de execução gerenciada. Ele não rastreia nenhum outro thread. Os threads podem ingressar no ambiente de execução gerenciado por meio da interoperabilidade COM (porque o runtime expõe os objetos gerenciados como objetos COM ao mundo não gerenciado), da função COM DllGetClassObject e da invocação de plataforma.

Quando um thread não gerenciado, por exemplo, um COM Callable Wrapper, ingressa no runtime, o sistema verifica o repositório de threads locais do thread em questão para procurar um objeto Thread interno gerenciado. Caso o sistema encontre um thread desse tipo, o runtime fica ciente sobre ele. No entanto, se ele não conseguir encontrar um, o runtime criará um novo Thread objeto e o instalará no repositório local do thread.

No threading gerenciado, Thread.GetHashCode é a identificação estável do thread gerenciado. Durante o tempo de vida do thread, ele não colidirá com o valor de qualquer outro thread, independentemente do domínio do aplicativo do qual você obtém esse valor.

Mapeando do threading do Win32 para o threading gerenciado

A tabela a seguir mapeia os elementos do threading do Win32 com seu equivalente aproximado no runtime. Observe que esse mapeamento não representa uma funcionalidade idêntica. Por exemplo, TerminateThread não executa cláusulas finally, não libera recursos e não pode ser evitado. No entanto, Thread.Abort executa todo o código de reversão, recupera todos os recursos e pode ser negado usando ResetAbort. Leia a documentação de perto antes de fazer suposições sobre a funcionalidade.

No Win32 No Common Language Runtime
CreateThread Combinação de Thread e ThreadStart
TerminateThread Thread.Abort
SuspendThread Thread.Suspend
ResumeThread Thread.Resume
de suspensão Thread.Sleep
WaitForSingleObject no identificador de thread Thread.Join
ExitThread Nenhum equivalente
GetCurrentThread Thread.CurrentThread
SetThreadPriority Thread.Priority
Nenhum equivalente Thread.Name
Nenhum equivalente Thread.IsBackground
Próximo a CoInitializeEx (OLE32.DLL) Thread.ApartmentState

Threads gerenciados e apartments COM

Um thread gerenciado pode ser marcado para indicar que ele irá hospedar um single-threaded apartament ou um multithread apartament. (Para obter mais informações sobre a arquitetura de threading COM, consulte Processos, Threads e Apartments.) Os métodos GetApartmentState, SetApartmentState e TrySetApartmentState da classe Thread retornam e atribuem o estado de apartament de um thread. Se o estado não tiver sido definido, GetApartmentState retornará ApartmentState.Unknown.

A propriedade só pode ser definida quando o thread está no ThreadState.Unstarted estado; ela pode ser definida apenas uma vez para um thread.

Se o estado do apartment não for definido antes do início do thread, o thread será iniciado como MTA (multithreaded apartment). O thread finalizador e todos os threads controlados por ThreadPool são do tipo MTA.

Importante

No caso do código de inicialização do aplicativo, a única forma de controlar o estado do apartment é aplicar MTAThreadAttribute ou STAThreadAttribute ao procedimento do ponto de entrada.

Os objetos gerenciados que são expostos ao COM comportam-se como se houvesse um marshaler de thread livre agregado a eles. Em outras palavras, eles podem ser chamados por qualquer apartment COM no modo de threading livre. Os únicos objetos gerenciados que não exibem esse comportamento de thread livre são aqueles objetos que derivam de ServicedComponent ou StandardOleMarshalObject.

No mundo gerenciado, não há suporte para SynchronizationAttribute a menos que você use contextos e instâncias gerenciadas vinculadas ao contexto. Se você estiver usando os Serviços Empresariais, seu objeto deve derivar de ServicedComponent (que por sua vez é derivado de ContextBoundObject).

Quando o código gerenciado chama objetos COM, ele sempre segue as regras COM. Em outras palavras, ele faz a chamada por meio de proxies de apartment COM e COM+ 1.0 context wrappers, como ditado por OLE32.

Problemas de bloqueio

Se um thread fizer uma chamada não gerenciada no sistema operacional que bloqueou o thread no código não gerenciado, o runtime não assumirá o controle para Thread.Interrupt nem Thread.Abort. No caso do Thread.Abort, o runtime marca o thread como Abortar e assume o controle dele quando esse ingressa no código gerenciado. É preferível que você use o bloqueio gerenciado em vez de bloqueio não gerenciado. WaitHandle.WaitOne,WaitHandle.WaitAny, WaitHandle.WaitAll, Monitor.Enter, , Monitor.TryEnter, Thread.Joine GC.WaitForPendingFinalizersassim por diante são todos responsivos para Thread.Interrupt e para Thread.Abort. Além disso, se seu thread estiver em um single-threaded apartment, todas essas operações de bloqueio gerenciado enviarão mensagens para seu apartment enquanto o thread estiver bloqueado.

Fios e fibras

O modelo de threading do .NET não dá suporte a fibras. Você não deve chamar nenhuma função não gerenciada implementada usando fibras. Essas chamadas podem resultar em uma falha do runtime do .NET.

Consulte também