次の方法で共有


invalidApartmentStateChange MDA

Note

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

invalidApartmentStateChange マネージド デバッグ アシスタント (MDS) は、次の 2 つのどちらかの問題によってアクティブ化されます。

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

  • スレッドの COM アパートメント状態が予期せず変更された。

現象

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

  • スレッドの COM アパートメント状態が予想と異なります。 これが原因で、COMException (RCW) で呼び出しを行うときに、HRESULT が RPC_E_WRONG_THREAD の COMException、および InvalidCastException が発生する可能性があります。 これにより、一部のシングル スレッド COM が同時に複数のスレッドによってアクセスされ、そのために破損またはデータの損失につながることがあります。

原因

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

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

解決方法

スレッドの実行開始前に、スレッドのアパートメント状態を設定するか、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);
        }
    }
}

関連項目