Partilhar via


Apartamentos Multithreaded

Em um modelo de apartamento multithreaded, todos os threads no processo que foram inicializados como free-threaded residem em um único apartamento. Portanto, não há necessidade de marshal entre fios. Os threads não precisam recuperar e enviar mensagens porque o COM não usa mensagens de janela neste modelo.

Chamadas para métodos de objetos no apartamento multithreaded podem ser executadas em qualquer thread no apartamento. Não há serialização de chamadas; Muitas chamadas podem ocorrer para o mesmo método ou para o mesmo objeto simultaneamente. Os objetos criados no apartamento multithreaded devem ser capazes de lidar com chamadas em seus métodos de outros threads a qualquer momento.

Como as chamadas para objetos não são serializadas de forma alguma, a simultaneidade de objetos multithreaded oferece o mais alto desempenho e aproveita ao máximo o hardware multiprocessador para chamadas entre threads, processos cruzados e entre máquinas. Isso significa, no entanto, que o código para objetos deve fornecer sincronização em suas implementações de interface, normalmente através do uso de primitivas de sincronização, como objetos de evento, seções críticas, mutexes ou semáforos, que são descritos mais adiante nesta seção. Além disso, como o objeto não controla o tempo de vida dos threads que estão acessando-o, nenhum estado específico do thread pode ser armazenado no objeto (no armazenamento local do thread).

A seguir estão algumas considerações importantes sobre a sincronização para apartamentos multithreaded:

  • A COM fornece sincronização de chamadas apenas para apartamentos de thread único.
  • Apartamentos multithreaded não recebem chamadas enquanto fazem chamadas (no mesmo tópico).
  • Apartamentos multithreaded não podem fazer chamadas sincronizadas de entrada.
  • As chamadas assíncronas são convertidas em chamadas síncronas em apartamentos multithreaded.
  • O filtro de mensagens não é chamado para qualquer thread em um apartamento multithreaded.

Para inicializar um thread como free-threaded, chame CoInitializeEx, especificando COINIT_MULTITHREADED. Para obter informações sobre threading de servidor em processo, consulte In-Process Server Threading Issues.

Vários clientes podem chamar simultaneamente, a partir de threads diferentes, um objeto que suporte free-threading. Em servidores de thread livre fora de processo, COM, através do subsistema RPC, cria um pool de threads no processo do servidor e uma chamada de cliente (ou várias chamadas de cliente) pode ser entregue por qualquer um desses threads a qualquer momento. Um servidor fora de processo também deve implementar a sincronização em sua fábrica de classes. Objetos em processo de thread livre podem receber chamadas diretas de vários threads do cliente.

O cliente pode fazer o trabalho COM em vários threads. Todos os fios pertencem ao mesmo apartamento multithreaded. Os ponteiros de interface são passados diretamente de thread para thread dentro de um apartamento multithreaded, portanto, os ponteiros de interface não são empacotados entre seus threads. Os filtros de mensagem (implementações de IMessageFilter) não são usados em apartamentos multithreaded. O thread do cliente será suspenso quando fizer uma chamada COM para objetos fora do apartamento e será retomado quando a chamada retornar. As chamadas entre processos ainda são tratadas pela RPC.

Os threads inicializados com o modelo de thread livre devem implementar sua própria sincronização. Conforme mencionado anteriormente nesta seção, o Windows habilita essa implementação por meio das seguintes primitivas de sincronização:

  • Os objetos de evento fornecem uma maneira de sinalizar um ou mais threads de que um evento ocorreu. Qualquer thread dentro de um processo pode criar um objeto de evento. Um identificador para o evento é retornado pela função de criação de eventos, CreateEvent. Depois que um objeto de evento tiver sido criado, threads com um identificador para o objeto podem aguardar nele antes de continuar a execução.
  • As seções críticas são usadas para uma seção de código que requer acesso exclusivo a algum conjunto de dados compartilhados antes de poder ser executado e que é usada apenas pelos threads dentro de um único processo. Uma seção crítica é como uma catraca através da qual apenas um fio de cada vez pode passar, funcionando da seguinte forma:
    • Para garantir que não mais de um thread por vez acesse dados compartilhados, o thread principal de um processo aloca uma estrutura de dados de CRITICAL_SECTION global e inicializa seus membros. Um thread que entra em uma seção crítica chama a função EnterCriticalSection e modifica os membros da estrutura de dados.
    • Um thread que tenta entrar em uma seção crítica chama EnterCriticalSection que verifica se a estrutura de dados CRITICAL_SECTION foi modificada. Em caso afirmativo, outro thread está atualmente na seção crítica e o thread subsequente é colocado em suspensão. Um thread que sai de uma seção crítica chama LeaveCriticalSection, que redefine a estrutura de dados. Quando um thread sai de uma seção crítica, o sistema ativa um dos threads adormecidos, que então entra na seção crítica.
  • Mutexes executa a mesma função como uma seção crítica, exceto que o mutex é acessível a threads em execução em processos diferentes. Possuir um objeto mutex é como ter a palavra em um debate. Um processo cria um objeto mutex chamando a funçãoCreateMutex, que retorna um identificador. O primeiro thread que solicita um objeto mutex obtém a propriedade dele. Quando o thread termina com o mutex, a propriedade passa para outros threads por ordem de chegada.
  • Os semáforos são usados para manter uma contagem de referência em algum recurso disponível. Um thread cria um semáforo para um recurso chamando a função CreateSemaphore e passando um ponteiro para o recurso, uma contagem inicial de recursos e a contagem máxima de recursos. Esta função retorna um identificador. Um thread solicitando um recurso passa seu identificador de semáforo em uma chamada para a funçãoWaitForSingleObject. O objeto semáforo sonda o recurso para determinar se ele está disponível. Se assim for, o semáforo diminui a contagem de recursos e acorda o fio de espera. Se a contagem for zero, o thread permanecerá em suspensão até que outro thread libere um recurso, fazendo com que o semáforo aumente a contagem para um.

Acesso a interfaces entre apartamentos

Escolhendo o modelo de threading

Problemas de threading do In-Process Server

Processos, Threads e Apartamentos

Single-Threaded e Comunicação Multithreaded

Single-Threaded Apartments