invalidApartmentStateChange MDA

更新:2007 年 11 月

下列兩個問題中的任何一個問題都會啟動 invalidApartmentStateChange Managed 偵錯助理 (MDS):

  • 嘗試變更執行緒的 COM Apartment 狀態,卻已經由 COM 初始化為不同的 Apartment 狀態。

  • 執行緒的 COM Apartment 狀態意外變更。

症狀

  • 執行緒的 COM Apartment 狀態不是要求的狀態。如此會使 Proxy 被具有不同於目前執行緒模式的 COM 元件所使用。這樣在透過未針對跨 Apartment 封送處理 (Marshaling) 而設定的介面呼叫 COM 物件時,就會造成 InvalidCastException 的擲回。

  • 執行緒的 COM Apartment 狀態與預期不同。這樣在執行階段可呼叫包裝函式 (RCW) 進行呼叫時,就會造成具有 RPC_E_WRONG_THREAD 之 HRESULT 的 COMException,以及 InvalidCastException。這樣也會使一些單一執行緒 COM 元件同時被多個執行緒存取,並且因而導致損毀或資料遺失。

原因

  • 執行緒在先前初始化為不同的 COM Apartment 狀態。請注意,使用明確或隱含作業,都能設定執行緒的 Apartment 狀態。明確作業包括 Thread.ApartmentState 屬性,以及 SetApartmentStateTrySetApartmentState 方法。除非在啟動執行緒之前呼叫 SetApartmentState,否則使用 Start 方法建立的執行緒,都會隱含設定為 MTA。除非在主方法上有指定 STAThreadAttribute 屬性 (Attribute),否則應用程式的主執行緒也會隱含初始化為 MTA

  • 在執行緒上呼叫了具有不同並行模型的 CoUninitialize 方法 (或是 CoInitializeEx 方法)。

解決方式

在執行緒開始執行之前,設定其 Apartment 狀態,或是將 STAThreadAttribute 屬性或 MTAThreadAttribute 屬性套用到應用程式的主方法。

理想上,對於第二種原因,應該修改呼叫 CoUninitialize 方法的程式碼以延遲呼叫,直到執行緒將要結束,而且沒有任何 RCW 及其基礎 COM 元件依然由執行緒使用為止。然而,如果不可能修改呼叫 CoUninitialize 方法的程式碼,這樣沒有以這種方式初始化的執行緒就不該使用任何 RCW。

對執行階段的影響

這個 MDA 對 CLR 無效。

輸出

目前執行緒的 COM Apartment 狀態,以及程式碼嘗試套用的狀態。

組態

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

範例

下列程式碼範例示範會啟動這個 MDA 的情況。

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

請參閱

概念

診斷 Managed 偵錯助理的錯誤

Interop 封送處理概觀

參考

MarshalAsAttribute