invalidApartmentStateChange MDA
如果出现以下两个问题之一,则将激活 invalidApartmentStateChange 托管调试助手 (MDS):
尝试将一个线程的 COM 单元状态(已经由 COM 进行了初始化)更改为其他单元状态。
一个线程的 COM 单元状态意外更改。
症状
线程的 COM 单元状态不是所请求的单元状态。 这可能会导致代理将要用于的 COM 组件的线程处理模型与当前的不同。 如果调用 COM 对象时所通过的接口不是为跨单元封送处理设置的接口,则这种模型差异进而又会导致引发 InvalidCastException。
线程的 COM 单元状态不正常。 在对 运行时可调用包装 (RCW) 发出调用时,这可能导致 InvalidCastException 以及 RPC_E_WRONG_THREAD 的 HRESULT 出现 COMException。 这还有可能导致一些单线程 COM 组件同时由多个线程访问,进而导致损坏或数据丢失。
原因
早先将线程初始化成了一种不同的 COM 单元状态。 请注意,线程的单元状态既可以显式设置,也可以隐式设置。 显式操作包括 Thread.ApartmentState 属性以及 SetApartmentState 方法和 TrySetApartmentState 方法。 除非在线程启动之前调用 SetApartmentState,否则使用 Start 方法创建的线程会被隐式设置为 MTA。 除非在主方法上指定 STAThreadAttribute 特性,否则应用程序的主线程也会被隐式初始化为 MTA。
对线程调用了使用一种不同的并发模型的 CoUninitialize 方法(或 CoInitializeEx 方法)。
解决方法
在线程开始执行之前设置线程的单元状态,或将 STAThreadAttribute 特性或 MTAThreadAttribute 特性应用于应用程序的主方法。
对于第二个原因,理想情况下,应将调用 CoUninitialize 方法的代码修改为延迟此调用,一直延迟到线程即将终止并且没有任何 RCW 及其基础 COM 组件仍在被线程使用为止。 但是,如果无法修改调用 CoUninitialize 方法的代码,则不应从那些未以此方式初始化的线程使用任何 RCW。
对运行时的影响
此 MDA 对 CLR 无任何影响。
Output
当前线程的 COM 单元状态和代码尝试应用的状态。
配置
<mdaConfig>
<assistants>
<invalidApartmentStateChange />
</assistants>
</mdaConfig>
示例
下面的代码示例演示一种可激活此 MDA 的情况。
using System.Threading;
namespace ApartmentStateMDA
{
class Program
{
static void Main(string[] args)
{
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
}
}
}