invalidApartmentStateChange MDA
注意
本文特定于 .NET Framework。 它不适用于 .NET 的较新版本实现,包括 .NET 6 及更高版本。
invalidApartmentStateChange
托管调试助手 (MDS) 通过以下两种问题中的任何一种激活:
尝试将已由 COM 初始化的线程的 COM 单元状态更改为不同的单元状态。
线程的 COM 单元状态意外更改。
症状
线程的 COM 单元状态不符合请求。 这可能造成用于已有线程模型的 COM 组件的代理不同于现有代理。 进而可能导致在通过未设置为跨单元封送的接口调用 COM 对象时,引发 InvalidCastException。
线程的 COM 单元状态不同于预期。 这可能造成调用COMException (RCW) 时,出现 COMException、RPC_E_WRONG_THREAD 返回 HRESULT 以及 InvalidCastException。 这也可能造成部分单线程 COM 组件由多个线程同时访问,进而导致损坏或数据丢失。
原因
该线程之前已初始化为不同的 COM 单元状态。 请注意,可显式或隐式设置线程的单元状态。 显式操作包括 Thread.ApartmentState 属性以及 SetApartmentState 和 TrySetApartmentState 方法。 通过 Start 方法创建的线程可隐式设置为 MTA,除非 SetApartmentState 在线程创建之前就已调用。 应用程序主线程同样可隐式初始化为 MTA,除非在主方法上指定了 STAThreadAttribute 属性。
在线程上调用具有不同并发模型的
CoUninitialize
方法(或CoInitializeEx
方法)。
解决方法
在单元状态开始执行前对其进行设置,或将 STAThreadAttribute 属性或 MTAThreadAttribute 属性应用到应用程序的主方法。
对于第二种结果,理想情况下,需要将调用 CoUninitialize
方法的代码修改为延迟调用,直到线程即将终止并且该线程停止使用 RCW 及其基础 COM 组件。 但是,如果无法修改调用 CoUninitialize
方法的代码,则未采用此方法进行初始化的线程不能使用任何 RCW。
对运行时的影响
此 MDA 对 CLR 无任何影响。
输出
当前线程的 COM 单元状态和试图应用的代码状态。
Configuration
<mdaConfig>
<assistants>
<invalidApartmentStateChange />
</assistants>
</mdaConfig>
示例
以下代码示例展示了一种可激活该 MDA 的情况。
using System.Threading;
namespace ApartmentStateMDA
{
class Program
{
static void Main(string[] args)
{
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
}
}
}