invalidApartmentStateChange MDA
下列兩個問題中的任何一個問題都會啟動 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 屬性,以及 SetApartmentState 和 TrySetApartmentState 方法。 除非在啟動執行緒之前呼叫 SetApartmentState,否則使用 Start 方法建立的執行緒,都會隱含設定為 MTA。 除非在主方法上有指定 STAThreadAttribute 屬性 (Attribute),否則應用程式的主執行緒也會隱含初始化為 MTA。
在執行緒上呼叫了具有不同並行模型的 CoUninitialize 方法 (或是 CoInitializeEx 方法)。
解決方式
在執行緒開始執行之前,設定其 Apartment 狀態,或是將 STAThreadAttribute 屬性或 MTAThreadAttribute 屬性套用到應用程式的主方法。
理想上,對於第二種原因,應該修改呼叫 CoUninitialize 方法的程式碼以延遲呼叫,直到執行緒將要結束,而且沒有任何 RCW 及其基礎 COM 元件依然由執行緒使用為止。 然而,如果不可能修改呼叫 CoUninitialize 方法的程式碼,這樣沒有以這種方式初始化的執行緒就不該使用任何 RCW。
對執行階段的影響
這個 MDA 對 CLR 無效。
Output
目前執行緒的 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);
}
}
}