Share via


MDA invalidApartmentStateChange

O MDS (Assistente de Depuração Gerenciado) de invalidApartmentStateChange é ativado por qualquer um de dois problemas:

  • É feita uma tentativa de alterar o estado de apartment COM de um thread que já foi inicializado pelo COM para um estado de apartment diferente.

  • O estado de apartment COM de um thread é alterado inesperadamente.

Sintomas

  • Estado de apartment COM de um thread não é o que foi solicitado. Isso pode fazer com que proxies sejam usados para componentes COM que têm um modelo de threading diferente do atual. Isso, por sua vez, pode fazer com que uma InvalidCastException seja gerada ao chamar o objeto COM por meio de interfaces não definidas para marshaling entre apartments.

  • O estado de apartment COM do thread é diferente do esperado. Isso pode causar uma COMException com um HRESULT RPC_E_WRONG_THREAD, bem como uma InvalidCastException ao fazer chamadas em um RCW (Runtime Callable Wrapper). Isso também pode fazer com que alguns componentes COM de thread único sejam acessados por vários threads ao mesmo tempo, o que pode levar a danos ou perda de dados.

Causa

  • O thread foi inicializado anteriormente para um estado de apartment COM diferente. Observe que o estado de apartment de um thread pode ser definido explicitamente ou implicitamente. As operações explícitas incluem a propriedade Thread.ApartmentState e os métodos SetApartmentState e TrySetApartmentState. Um thread criado usando o método Start está implicitamente definido como MTA, a menos que SetApartmentState seja chamado antes do thread ser iniciado. O thread principal do aplicativo também é implicitamente inicializado como MTA, a menos que o atributo STAThreadAttribute seja especificado no método principal.

  • O método CoUninitialize (ou o método CoInitializeEx) com um modelo de simultaneidade diferente é chamado no thread.

Resolução

Defina o estado de apartment do thread antes que ele comece a executar ou então aplique o atributo STAThreadAttribute ou o atributo MTAThreadAttribute ao método principal do aplicativo.

Para a segunda causa, idealmente, o código que chama o método CoUninitialize deve ser modificado para atrasar a chamada até que o thread esteja prestes a ser encerrado e que não exista nenhum RCW nem componentes COM subjacentes que ainda estejam em uso pelo thread. No entanto, se não é possível modificar o código que chama o método CoUninitialize, então nenhum RCWs devem ser usado de threads cuja inicialização é cancelada dessa maneira.

Efeito sobre o runtime

Esse MDA não tem efeito sobre o CLR.

Saída

O estado de apartment COM do thread atual e o estado em que o código estava tentando aplicar.

Configuração

<mdaConfig>  
  <assistants>  
    <invalidApartmentStateChange />  
  </assistants>  
</mdaConfig>  

Exemplo

O exemplo de código a seguir demonstra uma situação que pode ativar esse MDA.

using System.Threading;  
namespace ApartmentStateMDA  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            Thread.CurrentThread.SetApartmentState(ApartmentState.STA);  
        }  
    }  
}  

Confira também