Partager via


Assistant Débogage managé invalidApartmentStateChange

L'Assistant Débogage managé (MDA, Managed Debugging Assistant) invalidApartmentStateChange est activé par l'un des deux problèmes suivants :

  • Une tentative est effectuée pour modifier l'état de cloisonnement COM d'un thread qui a déjà été initialisé par COM à un état de cloisonnement différent.

  • L'état de cloisonnement COM d'un thread change de manière inopinée.

Symptômes

  • L'état de cloisonnement COM d'un thread ne correspond pas à ce qui a été demandé. Cela peut entraîner l'utilisation de proxies pour des composants COM qui ont un modèle de thread différent du modèle courant. Cela peut également provoquer la levée d'une InvalidCastException lors de l'appel de l'objet COM via des interfaces qui ne sont pas définies pour le marshaling d'intercloisonnement.

  • L'état de cloisonnement COM du thread est différent de celui qui est attendu. Cela peut provoquer une COMException avec un HRESULT de RPC_E_WRONG_THREAD ainsi qu'une InvalidCastException lorsque des appels sont effectués sur un Wrapper pouvant être appelé par le runtime (RCW). Cela peut également conduire plusieurs threads à accéder en même temps à certains composants COM STA (Single-Threaded Apartment), ce qui risque d'entraîner l'altération ou la perte de données.

Cause

  • Le thread a été précédemment initialisé à un état de cloisonnement COM différent. Notez que l'état de cloisonnement d'un thread peut être défini explicitement ou implicitement. Les opérations explicites incluent la propriété Thread.ApartmentState et les méthodes SetApartmentState et TrySetApartmentState. MTA est implicitement affecté à un thread créé à l'aide de la méthode Start, à moins que SetApartmentState soit appelé avant le démarrage du thread. De même, la valeur MTA est implicitement affectée au thread principal de l'application, à moins que l'attribut STAThreadAttribute soit spécifié sur la méthode principale.

  • La méthode CoUninitialize (ou la méthode CoInitializeEx) avec un modèle d'accès concurrentiel différent est appelée sur le thread.

Solution

Définissez l'état de cloisonnement du thread avant que son exécution commence ou appliquez l'attribut STAThreadAttribute ou l'attribut MTAThreadAttribute à la méthode principale de l'application.

Dans l'idéal, pour la deuxième cause, le code qui appelle la méthode CoUninitialize doit être modifié pour différer l'appel jusqu'à ce que le thread soit sur le point de s'arrêter et qu'aucun des RCW ou leurs composants COM sous-jacents ne soient encore utilisés par le thread. Toutefois, s'il est impossible de modifier le code qui appelle la méthode CoUninitialize, aucun RCW ne doit être utilisé par des threads non initialisés de cette façon.

Effet sur le runtime

Ce MDA n'a aucun effet sur le CLR.

Sortie

L'état de cloisonnement COM du thread actuel et l'état que le code tentait d'appliquer.

Configuration

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

Exemple

L'exemple de code suivant illustre une situation qui peut activer ce MDA.

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

Voir aussi

Référence

MarshalAsAttribute

Concepts

Diagnostic d'erreurs avec les Assistants de débogage managés

Marshaling d'interopérabilité