通过


invalidApartmentStateChange MDA

注释

本文特定于 .NET Framework。 它不适用于 .NET 的较新版本实现,包括 .NET 6 及更高版本。

托管 invalidApartmentStateChange 调试助手(MDS)由以下两个问题之一激活:

  • 尝试将 COM 已初始化的线程的 COM 单元状态更改为其他单元状态。

  • 线程的 COM 单元状态意外更改。

症状

  • 线程的 COM 单元状态不是所请求的状态。 这可能会导致代理用于具有与当前模型不同的线程模型的 COM 组件。 这反过来可能会导致 InvalidCastException 通过未为跨单元封送设置的接口调用 COM 对象时引发。

  • 线程的 COM 单元状态与预期不同。 这可能会导致COMException对运行时可调用包装器(RCW)进行调用时出现RPC_E_WRONG_THREAD InvalidCastException HRESULT。 这也可能导致多个线程同时访问一些单线程 COM 组件,这可能会导致损坏或数据丢失。

原因

  • 该线程以前初始化为不同的 COM 单元状态。 请注意,线程的公寓状态可以显式或隐式设置。 显式操作包括 Thread.ApartmentState 属性和 SetApartmentState 方法和 TrySetApartmentState 方法。 使用该方法创建的 Start 线程将隐式设置为 MTA ,除非 SetApartmentState 在线程启动之前调用。 应用程序的主线程也隐式初始化为 MTA ,除非在 STAThreadAttribute main 方法上指定了属性。

  • CoUninitialize 线程上调用具有不同并发模型的方法(或 CoInitializeEx 方法)。

解决方案

在线程开始执行之前设置线程的公寓状态,或将 STAThreadAttribute 属性或 MTAThreadAttribute 属性应用于应用程序的主要方法。

对于第二个原因,最好修改调用 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);
        }
    }
}

另见