Respostas:
O modelo de encadeamento COM é chamado de "apartamento", em que o contexto de execução de objetos COM inicializados é associado a um único encadeamento (Single Thread Apartment) ou a vários encadeamentos (Multi Thread Apartment). Nesse modelo, um objeto COM, uma vez inicializado em um apartamento, faz parte desse apartamento durante o tempo de execução.
O modelo STA é usado para objetos COM que não são seguros para threads. Isso significa que eles não lidam com sua própria sincronização. Um uso comum disso é um componente de interface do usuário. Portanto, se outro encadeamento precisar interagir com o objeto (como pressionar um botão em um formulário), a mensagem será empacotada no encadeamento STA. O sistema de bombeamento de mensagens do Windows Forms é um exemplo disso.
Se o objeto COM puder manipular sua própria sincronização, o modelo MTA poderá ser usado onde vários segmentos tiverem permissão para interagir com o objeto sem chamadas empacotadas.
Tudo depende de como as chamadas para objetos são tratadas e de quanto proteção elas precisam. Objetos COM podem solicitar ao tempo de execução que os proteja contra serem chamados por vários threads ao mesmo tempo; aqueles que não o podem potencialmente ser chamados simultaneamente de diferentes threads, portanto, eles precisam proteger seus próprios dados.
Além disso, também é necessário que o tempo de execução impeça uma chamada de objeto COM de bloquear a interface do usuário, se uma chamada for feita a partir de um encadeamento da interface do usuário.
Um apartamento é um local para objetos viverem e eles contêm um ou mais segmentos. O apartamento define o que acontece quando as chamadas são feitas. As chamadas para objetos em um apartamento serão recebidas e processadas em qualquer encadeamento desse apartamento, com a exceção de que uma chamada de um encadeamento já no apartamento certo é processada por si só (ou seja, uma chamada direta ao objeto).
Os encadeamentos podem estar em um apartamento de thread único (nesse caso, eles são o único thread nesse apartamento) ou em um apartamento de vários threads. Eles especificam qual quando o thread inicializa o COM para esse segmento.
O STA é principalmente para compatibilidade com a interface do usuário, que está vinculada a um encadeamento específico. Um STA recebe notificações de chamadas para processar recebendo uma mensagem da janela em uma janela oculta; quando faz uma chamada de saída, inicia um loop de mensagem modal para impedir que outras mensagens da janela sejam processadas. Você pode especificar um filtro de mensagens a ser chamado, para que seu aplicativo possa responder a outras mensagens.
Por outro lado, todos os threads do MTA compartilham um único MTA para o processo. O COM pode iniciar um novo thread de trabalho para manipular uma chamada recebida se nenhum thread estiver disponível, até um limite de pool. Os threads que fazem chamadas de saída simplesmente bloqueiam.
Para simplificar, consideraremos apenas os objetos implementados nas DLLs, que anunciam no registro o que eles suportam, definindo o ThreadingModel
valor da chave de sua classe. Existem quatro opções:
ThreadingModel
valor não presente). O objeto é criado no thread da interface do usuário principal do host e todas as chamadas são empacotadas nesse segmento. A fábrica da classe será chamada apenas nesse segmento.Apartment
. Isso indica que a classe pode ser executada em qualquer segmento do modo de thread único. Se o encadeamento que o cria for um encadeamento STA, o objeto será executado nesse encadeamento; caso contrário, ele será criado no STA principal - se não houver STA principal, um encadeamento STA será criado para ele. (Isso significa que os threads MTA que criam objetos Apartment organizarão todas as chamadas para um thread diferente.) O factory de classe pode ser chamado simultaneamente por vários threads STA, portanto, ele deve proteger seus dados internos contra isso.Free
. Isso indica uma classe projetada para ser executada no MTA. Ele sempre será carregado no MTA, mesmo se criado por um encadeamento STA, o que novamente significa que as chamadas do encadeamento STA serão empacotadas. Isso ocorre porque um Free
objeto geralmente é escrito com a expectativa de que pode bloquear.Both
. Essas classes são flexíveis e carregam em qualquer apartamento em que foram criadas. No entanto, eles devem ser gravados para atender aos dois conjuntos de requisitos: eles devem proteger seu estado interno contra chamadas simultâneas, caso estejam carregadas no MTA, mas não devem bloquear, caso estejam carregadas em uma STA.No .NET Framework, basicamente basta usar [STAThread]
em qualquer segmento que crie interface do usuário. Os threads de trabalho devem usar o MTA, a menos que eles usem Apartment
componentes COM marcados; nesse caso, use o STA para evitar problemas de sobrecarga e escalabilidade, se o mesmo componente for chamado de vários threads (pois cada thread terá que esperar componente por sua vez). É muito mais fácil se você usar um objeto COM separado por thread, se o componente estiver no STA ou no MTA.
Acho as explicações existentes muito complicadas. Aqui está minha explicação em inglês simples:
STA: se um segmento criar um objeto COM definido como STA (ao chamar CoCreateXXX, você pode passar um sinalizador que define o objeto COM para o modo STA), somente esse segmento poderá acessar esse objeto COM (é isso que significa STA - Single Threaded Apartment ), outro encadeamento que tenta chamar métodos nesse objeto COM está silenciosamente transformado em entrega de mensagens para o encadeamento que cria (possui) o objeto COM. Isso é muito parecido com o fato de que apenas o encadeamento que criou um controle de interface do usuário pode acessá-lo diretamente. E esse mecanismo visa impedir operações complicadas de bloqueio / desbloqueio.
MTA: se um segmento cria um objeto COM definido como MTA, praticamente todo segmento pode chamar métodos diretamente nele.
Essa é basicamente a essência disso. Embora tecnicamente existam alguns detalhes que não mencionei, como no parágrafo 'STA', o segmento do criador deve ser STA. Mas isso é tudo o que você precisa saber para entender o STA / MTA / NA.
STA (Single Threaded Apartment) é basicamente o conceito de que apenas um thread irá interagir com o seu código por vez. As chamadas para o seu apartamento são organizadas através da janela de mensagens do Windows (usando uma janela não visível). Isso permite que as chamadas sejam enfileiradas e aguarde a conclusão das operações.
O MTA (Multi Threaded Apartment) é o local em que muitos threads podem operar ao mesmo tempo e o ônus é seu como desenvolvedor para lidar com a segurança do thread.
Há muito mais para aprender sobre modelos de encadeamento no COM, mas se você estiver com problemas para entender o que eles são, eu diria que entender o que é o STA e como ele funciona seria o melhor ponto de partida, porque a maioria dos objetos COM são STA.
Threads de apartamento, se um thread mora no mesmo apartamento que o objeto que está usando, é um thread de apartamento. Eu acho que este é apenas um conceito COM, porque é apenas uma maneira de falar sobre os objetos e threads com os quais eles interagem.
Cada EXE que hospeda controles COM ou OLE define o estado do apartamento. O estado do apartamento é por padrão STA (e para a maioria dos programas deve ser STA).
STA - Todos os controles OLE por necessidade devem residir em um STA. STA significa que seu objeto COM deve sempre ser manipulado no thread da interface do usuário e não pode ser passado para outros threads (como qualquer elemento da interface do usuário no MFC). No entanto, seu programa ainda pode ter muitos threads.
MTA - você pode manipular o objeto COM em qualquer thread do seu programa.
Pelo que entendi, o 'Apartment' é usado para proteger os objetos COM de problemas com vários threads.
Se um objeto COM não for seguro para threads, ele deve ser declarado como um objeto STA. Somente o encadeamento que o cria pode acessá-lo. O segmento de criação deve declarar-se como um segmento STA. Sob o capô, o encadeamento armazena as informações STA em seu TLS (armazenamento local do encadeamento). Chamamos esse comportamento de que o thread entra em um apartamento STA. Quando outros threads desejam acessar esse objeto COM, ele deve organizar o acesso ao thread de criação. Basicamente, o encadeamento de criação usa o mecanismo de mensagens para processar as chamadas de entrada.
Se um objeto COM for seguro para threads, ele deve ser declarado como um objeto MTA. O objeto MTA pode ser acessado por vários threads.
O código que chama dlls de objeto COM (por exemplo, para ler arquivos de dados proprietários), pode funcionar bem em uma interface do usuário, mas travar misteriosamente em um serviço. O motivo é que, a partir das interfaces de usuário do .Net 2.0, assumem STA (seguro para threads), enquanto os serviços assumem MTA (antes disso, os serviços assumem STA) .É necessário criar um thread STA para cada chamada COM em um serviço, podendo adicionar uma sobrecarga significativa.