Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Um processo é uma coleção de espaço de memória virtual, código, dados e recursos do sistema. Um thread é um código que deve ser executado serialmente em um processo. Um processador executa threads, não processos, portanto, cada aplicativo tem pelo menos um processo e um processo sempre tem pelo menos um thread de execução, conhecido como thread primário. Um processo pode ter vários threads além do thread primário.
Os processos se comunicam entre si por meio de mensagens, usando a tecnologia RPC (Chamada de Procedimento Remoto) da Microsoft para passar informações uns para os outros. Não há diferença para o chamador entre uma chamada proveniente de um processo em um computador remoto e uma chamada proveniente de outro processo no mesmo computador.
Quando um thread começa a ser executado, ele continua até ser morto ou até ser interrompido por um thread com prioridade mais alta (por uma ação do usuário ou pelo agendador de thread do kernel). Cada thread pode executar seções separadas de código ou vários threads podem executar a mesma seção de código. Os threads que executam o mesmo bloco de código mantêm pilhas separadas. Cada thread em um processo compartilha as variáveis e recursos globais desse processo.
O agendador de thread determina quando e com que frequência executar um thread, de acordo com uma combinação do atributo de classe de prioridade do processo e a prioridade base do thread. Você define o atributo de classe de prioridade de um processo chamando a função SetPriorityClass e define a prioridade base de um thread com uma chamada para SetThreadPriority.
Os aplicativos multi-threaded devem evitar dois problemas de threading: deadlocks e corridas. Um deadlock ocorre quando cada thread está aguardando que o outro faça algo. O controle de chamada COM ajuda a evitar deadlocks em chamadas entre objetos. Uma condição de corrida ocorre quando um thread termina antes do outro do qual depende, fazendo com que o primeiro use um valor não inicializado porque o segundo ainda não forneceu um valor válido. O COM oferece algumas funções desenvolvidas especificamente para ajudar a evitar condições de disputa em servidores externos ao processo. (Consulte auxiliares de implementação de servidor fora de processo.)
O Apartment e a arquitetura de threading do COM
Embora o COM dê suporte ao modelo de thread único por processo predominante antes da introdução de vários threads de execução, você pode escrever código para aproveitar vários threads, resultando em aplicativos mais eficientes, permitindo que um thread seja executado enquanto outro thread aguarda a conclusão de alguma operação demorada.
Nota
Usar vários threads não é uma garantia de melhor desempenho. Na verdade, como a fatoração de thread é um problema difícil, o uso de vários threads geralmente causa problemas de desempenho. A chave é usar vários threads somente se você tiver certeza do que está fazendo.
Em geral, a maneira mais simples de entender a arquitetura de encadeamento do COM é pensar em todos os objetos COM no processo como estando divididos em grupos chamados apartments. Um objeto COM reside exatamente em um apartment, no sentido de que os métodos possam ser chamados diretamente apenas por um thread que pertença a esse apartament. Qualquer outro thread que queira chamar o objeto deve passar por um proxy.
Há dois tipos de apartments: apartaments de thread única e apartaments multithreaded.
Importante
Escolhendo um modelo de apartamento (STA vs MTA):
| Apartamento |
CoInitializeEx sinalizador |
Usar quando |
|---|---|---|
| STA (single-threaded) | COINIT_APARTMENTTHREADED |
Seu thread tem um loop de mensagem (threads de interface do usuário) ou você está usando objetos COM que exigem uma bomba de mensagem (controles ActiveX, objetos Shell, arrastar e soltar). |
| MTA (multithreaded) | COINIT_MULTITHREADED |
Seu thread executa um trabalho em segundo plano sem loop de mensagem e os objetos COM que você usa são thread-safe ou ágeis. |
Armadilha de deadlock comum: um thread STA deve processar mensagens (por meio de GetMessage/DispatchMessage ou equivalente). Se um thread STA bloquear em um primitivo de sincronização (por exemplo, WaitForSingleObject) sem processar mensagens, as chamadas COM recebidas para objetos nesse apartament jamais serão entregues, o que causa deadlocks. Use CoWaitForMultipleHandles ou MsgWaitForMultipleObjects em vez de esperas brutas em um thread STA.
- Os single-threaded apartments consistem em exatamente um thread, de maneira que todos os objetos COM que residam em um single-threaded apartment podem receber chamadas de método apenas de um thread pertencente a esse apartament. Todas as chamadas de método para um objeto COM em um single-threaded apartment são sincronizadas com a fila de mensagens do Windows para o thread do single-threaded apartment. Um processo com um único thread de execução é simplesmente um caso especial desse modelo.
- Os multi-threaded apartments consistem em um ou mais threads, de maneira que todos os objetos COM que residam em um multi-threaded apartment possam receber diretamente chamadas de método de qualquer um dos threads que pertençam ao multi-threaded apartment. Os threads em um multi-threaded apartment usam um modelo chamado free-threading. As chamadas para objetos COM em um multi-threaded apartment são sincronizadas pelos próprios objetos.
Nota
Para obter uma descrição da comunicação entre single-threaded apartments e multi-threaded apartments dentro do mesmo processo, consulte Comunicação single-threaded e multi-threaded.
Um processo pode ter zero ou mais single-threaded apartments e zero ou um multi-threaded apartment.
Em um processo, o apartamento principal é o primeiro a ser inicializado. Em um single-threaded process, este é o único apartament. O marshaling dos parâmetros de chamada é realizado entre apartments, e o COM manipula a sincronização por meio de mensagens. Se você definir várias threads em um processo como livres, todas as threads livres residirão em um único apartamento, os parâmetros serão passados diretamente para qualquer thread no apartamento, e você deverá cuidar de toda a sincronização. Em um processo com threads livres e apartment threading, todos os threads livres residem em um único apartamento, e todos os outros apartamentos são single-threaded apartments. Um processo que realiza trabalho COM é uma coleção de apartaments com, no máximo, um multi-threaded apartment, mas qualquer número de single-threaded apartments.
Os modelos de threading em COM fornecem o mecanismo para clientes e servidores que usam diferentes arquiteturas de threading trabalharem juntos. Há suporte natural para chamadas entre objetos com diferentes modelos de threading em processos diferentes. Da perspectiva do objeto de chamada, todas as chamadas para objetos fora de um processo se comportam de forma idêntica, não importa como o objeto que está sendo chamado é encadeado. Da mesma forma, na perspectiva do objeto chamado, as chamadas recebidas se comportam de forma idêntica, independentemente do modelo de encadeamento do chamador.
A interação entre um cliente e um objeto fora de processo é simples, mesmo quando eles usam modelos de threading diferentes porque o cliente e o objeto estão em processos diferentes. O COM, interposto entre o cliente e o servidor, pode fornecer o código para que os modelos de threading interoperem, usando marshaling padrão e RPC. Por exemplo, se um objeto single-threaded for chamado simultaneamente por vários clientes free-threaded, as chamadas serão sincronizadas por COM colocando mensagens de janela correspondentes na fila de mensagens do servidor. O apartament do objeto receberá uma chamada sempre que recuperar e expedir mensagens. No entanto, alguns cuidados devem ser tomados para garantir que os servidores em processo interajam corretamente com seus clientes. (Consulte Problemas de encadeamento de threads no servidor em processo.)
A questão mais importante na programação com um modelo multithread é tornar seu código seguro para threads, de modo que as mensagens destinadas a uma thread específica cheguem apenas a essa thread e que o acesso às threads seja protegido.
Para obter mais informações, consulte os seguintes tópicos:
- escolhendo o modelo de threading
- Apartamentos de Thread Única
- Apartamentos com múltiplos threads
- Thread único e comunicação com múltiplos threads
- Problemas de encadeamento de threads do servidor In-Process
- Acesso a Interfaces em Diferentes Apartamentos