STAThread e multithreading

102

Do artigo do MSDN sobre STAThread:

Indica que o modelo de threading COM para um aplicativo é single-threaded apartment (STA).

(Para referência, este é o artigo completo .)

Apartamento single-threaded ... OK, isso passou pela minha cabeça. Além disso, li em algum lugar que, a menos que seu aplicativo use interoperabilidade COM, esse atributo na verdade não faz nada. Então, o que exatamente ele faz e como afeta os aplicativos multithread? Os aplicativos multithread (que inclui qualquer coisa, desde qualquer pessoa usando Timers até chamadas de método assíncronas, não apenas threadpools e similares) devem usar MTAThread, mesmo que seja 'apenas para segurança'? O que STAThread e MTAThread realmente fazem?

Matthew Scharley
fonte

Respostas:

60

O segmento de apartamento é um conceito COM; se você não estiver usando COM e nenhuma das APIs que você chama usa COM "nos bastidores", não precisa se preocupar com os apartamentos.

Se você precisa estar ciente dos apartamentos, os detalhes podem ser um pouco complicados ; uma versão provavelmente simplificada demais é que os objetos COM marcados como STA devem ser executados em um STAThread e os objetos COM marcados como MTA devem ser executados em um thread MTA. Usando essas regras, o COM pode otimizar chamadas entre esses diferentes objetos, evitando o empacotamento onde não é necessário.

Bruce
fonte
7
Isso é simplificado demais. Objetos multithread podem ser executados em qualquer thread. Objetos threaded de apartamento só podem ser executados no apartamento em que foram criados.
1800 INFORMAÇÕES,
28
Uma chamada de um objeto STA em um thread STA, para um objeto MTA, irá empacotar para um thread MTA (a menos que o objeto MTA implemente o empacotador de thread livre). Como eu disse, os detalhes podem se complicar. (Eu trabalhei na equipe COM por vários anos, sorrindo )
Bruce,
9
Às vezes, você precisa estar ciente disso, mesmo se não estiver usando o COM diretamente. Um thread deve usar o modelo Single-Threaded Apartment se exibir qualquer janela gráfica. É por isso que [STAThread] é sempre exibido na parte superior do método principal em um aplicativo de formulários do Windows.
Justin Ethier
6
Algo como uma caixa de diálogo de fonte ou arquivo não poderia usar COM sem você saber? Eu presumiria que sim internamente, isso não significaria que quase todos os aplicativos do Windows Forms exigiriam que o STAThread fosse definido? Perdoe minha suposição ingênua, pois na verdade eu não fiz programação COM.
Brett Ryan
4
Uma resposta mais detalhada para aqueles que estão interessados: stackoverflow.com/questions/4154429/apartmentstate-for-dummies
jgauffin
3

O que faz, ele garante que CoInitializeseja chamado especificando COINIT_APARTMENTTHREADED como o parâmetro. Se você não usar nenhum componente COM ou controle ActiveX, ele não terá nenhum efeito sobre você. Se você fizer isso, será crucial.

Os controles com thread de apartamento são efetivamente com thread único; as chamadas feitas a eles só podem ser processadas no apartamento em que foram criados.

Mais alguns detalhes do MSDN:

Objetos criados em um single-threaded apartment (STA) recebem chamadas de método apenas do thread de seu apartment, portanto, as chamadas são serializadas e chegam apenas nos limites da fila de mensagens (quando a função Win32 PeekMessage ou SendMessage é chamada).

Objetos criados em um thread COM em um apartamento multithread (MTA) devem poder receber chamadas de método de outros threads a qualquer momento. Normalmente, você implementaria alguma forma de controle de simultaneidade no código de um objeto multithread usando primitivos de sincronização Win32, como seções críticas, semáforos ou mutexes para ajudar a proteger os dados do objeto.

Quando um objeto configurado para ser executado no NTA (Neutral Threaded Apartment) é chamado por um thread que está em um STA ou no MTA, esse thread é transferido para o NTA. Se este thread subsequentemente chamar CoInitializeEx, a chamada falhará e retornará RPC_E_CHANGED_MODE.

1800 INFORMAÇÕES
fonte
O artigo do MSDN é útil do ponto de vista do COM, mas você pode me dizer quando o .NET chama CoInitialize()em resposta ao STAThreadatributo / ApartmentState? Observação: o artigo no MSDN está aqui: função CoInitializeEx .
jrh
O thread-> SetApartment usa CoInitialize()internamente? Rastreei o Atributo STAThread todo o caminho até lá, mas a trilha esfriou (não consigo encontrar a fonte Thread::SetApartment). A classe Thread de thread.h (o thread COM.h) está documentada em algum lugar? É MFC, ATL ou outra coisa?
jrh
@jrh Não sei mais detalhes do que isso, desculpe
1800 INFORMAÇÕES
-15

STAThread é escrito antes da função principal de um projeto C # GUI. Ele não faz nada, mas permite que o programa crie um único thread.

Zeinth
fonte