最近在解决问题的时候不得不使用线程,从而接触到了STA和MTA,度娘给的解释大多语焉不详。在WikiPedia上面看到了比较清楚的描述,趁着能访问的间隙麻利的摘抄下来分享和自我提升。
单元类型 | 描述 |
---|---|
单线程单元( STA ), (ThreadingModel= Apartment ) | 只用单个线程执行对象的方法。在这样的安排中,来自单元外线程的方法调用被系统 编组 并自动排队(通过标准的 Windows 消息队列)。因此,COM 运行时提供自动同步以确保对象的每个方法调用始终在调用另一个方法之前执行完成。因此,开发人员无需担心线程锁定或竞争条件。 |
多线程单元( MTA ), (ThreadingModel= Free ) | COM 运行时不提供同步,并且允许多个线程同时调用 COM 对象。因此,COM 对象需要执行自己的同步,以防止多个线程同时访问导致竞争条件。从 STA 中的线程对 MTA 对象的调用也被编组。 |
动态确定的单元(ThreadingModel= Both) | 在 两个单元 模式下,服务器在对象创建时自动选择 STA 或 MTA 以匹配调用线程的单元类型。 当 STA 线程访问 MTA 服务器时,这对于避免编组开销很有用。 |
线程中性单元( NA ),(ThreadingModel= Neutral ) | 一个没有任何分配线程的特殊公寓。当 STA 或 MTA 线程在同一进程中调用 NA 对象时,调用线程会暂时离开其单元并直接在 NA 中执行代码,无需任何线程切换。因此,人们可以将 NA 视为对高效跨部门方法调用的优化。 |
大意就是单线程单元访问外部是串行的,在前一个任务完全结束之前不会进行下一个任务(an object is always executed to completion before another is invoked),开发者一般情况下可以不用担心竞争和死锁等问题(The developer therefore does not need to worry about thread locking or race conditions.)。
线程模式分为STA(Single Threaded Apartment) 单线程单元 和 MTA 多线程单元(Multi-Threaded Apartment)。任何一个WPF程序,Main方法前必须有一个[STAThread]特性,否则编译会失败。这个特性用来申明该应用程序的初始线程模型为STA,以便和COM兼容。STA是.NET之前,旧的COM年代的词汇。
1.介绍
STA线程单元的运行方式称为Object-per-Client模式,就是在COM库初始化的时候创建一个内存结构,然后让它和调用CoInitialize的线程相关联。这个内存结构针对每个线程都会有一个。支持STA的COM对象只能在创建它的线程里被使用,其它线程如果再创建它就会失败。在STA线程模式中,对线程的所有调用都放到一个队列中,然后逐个处理这些调用。因此,STA线程永远不会同时执行多个方法。STA线程有自己的专有数据,它们不会在线程之间共享数据。这种特征使这一线程模式非常安全,避免了数据的损坏和同步问题。
MTA多线程单元,COM库在进程中创建一个内存结构,这个内存结构在整个进程中只能有一个,然后让它和调用CoInitializeEx的线程相关联。支持MTA的COM对象可以在任意线程里被使用。多个针对它的调用都会被封装成为消息。COM运行时不提供同步,允许多个线程同时调用COM对象。因此,COM对象需要执行它们自己的同步,以防止来自多个线程的同步访问,产生竞争条件。
2.区别
在同一个单元中,单线程单元(STA)访问外部是串行的,在前一个任务完全结束之前不会进行下一个任务,而MTA单元则可以同时运行多个线程,并使用所有可用的共享数据,由于MTA模式支持同时执行多个线程,所以调用者应负责同步多个线程之间的全局数据。
其实STA和MTA是COM规定的一套线程模型,用于保障多线程情况下你的组件代码的同步。比如说有一个COM对象它内部有一个静态变量 gHello,那么这个对象无论生成多少实例对于gHello在内存中只能有一份,那么如果有两个不同的实例在两个线程里面同时去读写它,就有可能出错,所以就要就要有种机制进行同步保护,STA或者MTA就是这种机制。