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 属性以及 SetApartmentStateTrySetApartmentState 方法。 通过 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);
        }
    }
}

请参阅