Processos, threads e apartamentos

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 em série dentro de 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 principal.

Os processos se comunicam entre si por meio de mensagens, usando a tecnologia RPC (Remote Procedure Call) da Microsoft para passar informações uns aos outros. Não há diferença para o chamador entre uma chamada vinda de um processo em uma máquina remota e uma chamada vinda de outro processo na mesma máquina.

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 threads 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 os 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 da 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.

Aplicativos multithreaded devem evitar dois problemas de threading: deadlocks e corridas. Um deadlock ocorre quando cada thread está esperando 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 de 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 fornece algumas funções especificamente projetadas para ajudar a evitar condições de corrida em servidores fora de processo. (Veja Auxiliares de implementação de servidor fora do processo.)

O apartamento e a arquitetura COM Threading

Embora o COM ofereça 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.

Observação

Usar vários threads não é garantia de melhor desempenho. Na verdade, como a fatoração de threads é 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 muita certeza do que está fazendo.

 

Em geral, a maneira mais simples de visualizar a arquitetura de threading COM é pensar em todos os objetos COM no processo como divididos em grupos chamados apartamentos. Um objeto COM vive exatamente em um apartamento, no sentido de que seus métodos podem legalmente ser chamados diretamente apenas por um fio que pertence a esse apartamento. Qualquer outro thread que queira chamar o objeto deve passar por um proxy.

Existem dois tipos de apartamentos: apartamentos single-threaded e apartamentos multithreaded.

  • Os apartamentos de thread único consistem exatamente em um thread, de modo que todos os objetos COM que vivem em um apartamento de thread único podem receber chamadas de método somente do thread que pertence a esse apartamento. Todas as chamadas de método para um objeto COM em um apartamento de thread único são sincronizadas com a fila de mensagens do Windows para o thread do apartamento de thread único. Um processo com um único segmento de execução é simplesmente um caso especial deste modelo.
  • Os apartamentos multithreaded consistem em um ou mais threads, portanto, todos os objetos COM que vivem em um apartamento multithreaded podem receber chamadas de método diretamente de qualquer um dos threads que pertencem ao apartamento multithreaded. Os threads em um apartamento multithreaded usam um modelo chamado free-threading. As chamadas para objetos COM em um apartamento multithreaded são sincronizadas pelos próprios objetos.

Observação

Para obter uma descrição da comunicação entre apartamentos single-threaded e apartamentos multithreaded dentro do mesmo processo, consulte Single-Threaded and Multithreaded Communication.

 

Um processo pode ter zero ou mais apartamentos single-threaded e zero ou um apartamento multithreaded.

Em um processo, o apartamento principal é o primeiro a ser inicializado. Em um processo de thread único, este é o único apartamento. Os parâmetros de chamada são agrupados entre apartamentos, e o COM lida com a sincronização por meio de mensagens. Se você designar vários threads em um processo para ser free-threaded, todos os threads livres residem em um único apartamento, os parâmetros são passados diretamente para qualquer thread no apartamento e você deve lidar com toda a sincronização. Em um processo com threading livre e threading de apartamento, todos os fios livres residem em um único apartamento e todos os outros apartamentos são apartamentos de thread único. Um processo que faz o trabalho COM é uma coleção de apartamentos com, no máximo, um apartamento multithreaded, mas qualquer número de apartamentos single-threaded.

Os modelos de threading em COM fornecem o mecanismo para que clientes e servidores que usam arquiteturas de threading diferentes trabalhem juntos. Chamadas entre objetos com diferentes modelos de threading em diferentes processos são naturalmente suportadas. 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, da perspectiva do objeto que está sendo chamado, as chamadas que chegam se comportam de forma idêntica, independentemente do modelo de threading do chamador.

A interação entre um cliente e um objeto fora do processo é direta, mesmo quando eles usam modelos de threading diferentes, porque o cliente e o objeto estão em processos diferentes. COM, interposto entre o cliente e o servidor, pode fornecer o código para os modelos de threading interoperarem, usando marshaling padrão e RPC. Por exemplo, se um objeto de thread único for chamado simultaneamente por vários clientes de thread livre, as chamadas serão sincronizadas por COM colocando as mensagens de janela correspondentes na fila de mensagens do servidor. O apartamento do objeto receberá uma ligação cada vez que recuperar e enviar mensagens. No entanto, alguns cuidados devem ser tomados para garantir que os servidores em processo interajam corretamente com seus clientes. (Veja Problemas de threading do servidor em processo.)

O problema mais importante na programação com um modelo multithreaded é tornar seu código thread-safe para que as mensagens destinadas a um thread específico vão apenas para esse thread e o acesso aos threads é protegido.

Para Mais informações, consulte os seguintes tópicos: