次の方法で共有


invalidApartmentStateChange MDA

この記事は .NET Framework に固有のものです。 .NET 6 以降のバージョンを含む、.NET の新しい実装には適用されません。

invalidApartmentStateChange マネージド デバッグ アシスタント (MDS) は、次の 2 つの問題のいずれかでアクティブ化されます。

  • 既に COM によって初期化されているスレッドの COM アパートメント状態を別のアパートメント状態に変更しようとしました。

  • スレッドの COM アパートメント状態が予期せず変化します。

Symptoms

  • スレッドの COM アパートメント状態は、要求されたものではありません。 これにより、現在とは異なるスレッド モデルを持つ COM コンポーネントにプロキシが使用される可能性があります。 これにより、アパートメント間マーシャリング用に設定されていないインターフェイスを介して COM オブジェクトを呼び出すと、 InvalidCastException がスローされる可能性があります。

  • スレッドの COM アパートメント状態が予想と異なります。 これにより、ランタイム呼び出し可能ラッパー (RCW) で呼び出しを行うときに、HRESULT RPC_E_WRONG_THREADとInvalidCastExceptionを使用したCOMExceptionが発生する可能性があります。 これにより、一部のシングル スレッド COM コンポーネントが複数のスレッドから同時にアクセスされ、破損やデータ損失につながる可能性があります。

原因

  • スレッドは、以前は別の COM アパートメント状態に初期化されていました。 スレッドのアパートメント状態は、明示的または暗黙的に設定できることに注意してください。 明示的な操作には、 Thread.ApartmentState プロパティと SetApartmentState メソッドと TrySetApartmentState メソッドが含まれます。 Start メソッドを使用して作成されたスレッドは、スレッドが開始される前にSetApartmentStateが呼び出されない限り、暗黙的にMTAに設定されます。 アプリケーションのメイン スレッドも、main メソッドで STAThreadAttribute 属性が指定されていない限り、MTAに暗黙的に初期化されます。

  • 別のコンカレンシー モデルを持つ CoUninitialize メソッド (または CoInitializeEx メソッド) がスレッドで呼び出されます。

Resolution

スレッドの実行を開始する前に、スレッドのアパートメント状態を設定するか、 STAThreadAttribute 属性または MTAThreadAttribute 属性をアプリケーションのメイン メソッドに適用します。

2 番目の原因として、理想的には、 CoUninitialize メソッドを呼び出すコードを変更して、スレッドが終了し、RCW とその基になる COM コンポーネントがスレッドによってまだ使用されていないまで呼び出しを遅延させる必要があります。 ただし、 CoUninitialize メソッドを呼び出すコードを変更できない場合は、この方法で初期化されていないスレッドから RCW を使用しないでください。

ランタイムへの影響

この MDA は CLR には影響しません。

アウトプット

現在のスレッドの COM アパートメント状態と、コードが適用しようとした状態。

コンフィギュレーション

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

次のコード例は、この MDA をアクティブ化できる状況を示しています。

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

こちらも参照ください