如果我们创建一个类似于此的线程:Thread.SetApartmentState(STA);
,则它无法运行标有[MTAThread]
属性的代码。
我们在Windows和控制台应用程序中看到[STAThread]
,但我从未见过具有[MTAThread]
属性的代码,并且不知道哪些.NET库使用此属性。
我的问题是,与具有MTA单元状态(自然.NET线程)的线程相比,将单元状态设置为STA的线程有什么限制?
答案 0 :(得分:18)
然后它无法运行标有[MTAThread]属性的代码。
这不是它的工作原理。公寓类型是线程的属性,而不是方法。您会看到[STAThread]属性仅应用于.NET程序的Main()方法。它确定为运行程序而创建的第一个线程的单元类型。必要,因为在线程运行后无法调用SetApartmentState()。除此之外,该属性没有意义,线程在其生命周期内保留在STA中。你永远不会看到[MTAThread],因为这是默认值。
STA的线程有一些限制。它永远不会阻塞,因为这将阻止并经常死锁任何试图调用公寓线程COM对象的方法的代码。并且它必须泵送一个消息循环,以便COM可以编组来自另一个线程的方法调用。 Marshaled方法调用只能在线程“空闲”时执行,而不是忙于执行任何代码。消息循环提供“不忙”状态。
COM组件也有要求。它必须支持编组,或者通过将自身限制为Automation支持的类型子集,以便可以使用标准编组器。或者通过为自定义封送提供代理/存根对。 HKCR\Interface\{iid}\ProxyStubClsid32
注册表项确定编组的完成方式。
明确支持在STA和MTA线程之间共享公寓线程对象。 STA线程必须创建它,MTA线程(或其他STA线程)上的任何调用都被封送。这确保了组件只能看到在同一线程上进行的调用,从而确保线程安全。无需额外锁定。
最后但并非最不重要的是,如果您在MTA线程上创建一个公寓线程COM对象,那么COM将自动创建一个STA线程,为其提供安全的家。唯一的失败模式是COM组件不支持封送。这样做的一个缺点是每个调用都将被封送。那很慢。
答案 1 :(得分:0)
如果您不使用COM,我认为这没有任何区别。如果这样做,那么在某些情况下,COM对象可能只能从一种或另一种类型的线程访问。如果COM对象在两个公寓中都有效,那么请尝试进行性能测试。或者阅读MSDN上的COM公寓。但我不认为这对性能很重要,而是设计选择或其他。