线程公寓州

kou*_*des 4 c# multithreading

所有,

我一直在C#中使用线程一段时间,但我仍然对线程的公寓状态真正意味着什么感到困惑.我知道WinForms必须始终使用STA公寓状态(而不是MTA),但我仍然不清楚公寓状态是什么.

Han*_*ant 9

COM有很高的目标.其中之一是线程是一个非常难以正确编程的编程细节,应由支持库管理.与.NET非常不同的是,完全由您来使用线程安全的非线程安全的类.

这通过注册表工作,COM coclass发布ThreadingModel注册表项,说明它支持哪种类型的线程.到目前为止,大多数人都使用"公寓",这是一种有点不明确的说法"我不支持多线程".这是COM的一个信号,以确保以线程安全的方式调用所有方法.如果程序从工作线程调用方法,那么COM负责将来自worker的调用封送到创建实例的线程.因此,自动确保以线程安全的方式使用服务器.与Control.Invoke和Dispatcher.Invoke的工作方式不同,但完全自动.

这当然是一个奇妙的魔术,但你的程序确实需要合作一点.如果没有你的帮助,COM无法组织这样的电话.当您的程序创建一个线程时,它必须调用CoInitialize()来告诉COM基础结构您要参与COM调用.那时,你必须告诉它你创建了什么的线程.有两种,以"公寓"类型为特色.有STA(单线程公寓)和MTA(多个).STA线程是不支持线程的COM组件的好客主页.MTA线程不是.

虽然这种公寓附有价格标签.创建STA时,您必须遵循STA规则.这有点夸张:

  • 必须泵送Windows消息循环
  • 永远不能阻止线程

消息循环是COM将一个线程调用到另一个线程的机制.永不阻止规则是防止死锁所必需的.虽然是严苛的,但它是程序的UI线程的工作方式.这不是巧合.

还有一个价格标签附加在MTA线程上创建公寓线程COM对象.这样的线程不是一个好的家,它不遵循STA规则.COM无法提供帮助,并且可以调整方法调用.COM介入并实际创建自己的STA线程,为对象提供一个好客的家.很好,但并不便宜,因为它烧掉了一个线程并且每个方法调用都被封送,这给每次调用增加了很多开销.

COM线程支持是相当不错的,它可以在98%的时间内处理所有事情,而无需执行任何特殊操作.然而,2%可以给你一个巨大的偏头痛,你可以做很少的事情来打击它.它的扩展性也非常差,可能是.NET没有任何相似之处的最大原因.

虽然COM似乎已经死了,但公寓在Windows编程中仍然是一个非常大的问题..NET框架明确支持它们.例如,在STA线程上调用Thread.Join()或Monitor.Enter(),由COM显式禁止,使CLR泵成为消息循环.其他工件是您在GUI应用程序的Main()方法和Thread.SetApartmentState()上看到的[STAThread]属性,这是获取CLR调用CoInitialize()的正确方法.剪贴板,拖放和shell对话框(如OpenFileDialog)等GUI功能明确要求STA工作.创建任何窗口的线程应始终是STA线程.