STA和MTA 之 COM和套间

COM技术过时了吗?这句话也对也不对 。从技术上讲 , 确实COM的使用率在下降 , 但是从思想上来说 , COM的面向接口的思想正在被Java和.NET发扬光大 。那我们还需要和COM打交道吗?这取决于你工作的领域 。虽然现在微软的平台在慢慢向着.NET迁移 , 不过 , 在维护原有非托管代码 , 编写和系统组件打交道的程序 , 以及使用CLR调用非托管代码的时候 , COM或多或少都是不可避免的 。与COM打交道就没法不谈到套间() 。套间是COM中一个非常有用然而也非常难以理解的一个概念 , 可以说COM中的很多问题都和套间有关 , 理解了套间 , 离完全理解COM就更近了一步 , 本文将分若干次讨论套间的基础知识以及在.NET中的应用 。
什么是套间()
套间是COM为了简化对象对多线程的支持而推出的一套机制 , 用于指定线程和COM对象的多线程特性 , 并且对不同特性的套间之间的调用提供同步支持 , 保证不同多线程特性的对象之间可以互相正确调用而不会引入同步问题 , 简化编程(实际上可能搞得更复杂了) 。比如 , 如果某个对象编写的时候忘记考虑多线程 , 或者没有时间考虑 , 或者没有必要提供实现多线程的支持 , 这个时候可以将对象指定为STA , 让COM自动管理对该对象的调用 , 保证对象可以被正确调用 , 即使是多线程的调用也会被串行化(依次调用 , 而非同时调用) 。反之 , 如果一个对象支持多线程调用 , 那么它可以被标记为MTA , COM会允许对其进行多线程的调用 。
对于套间需要注意下面几点:
1、套间并不是一个真实存在的一个区域 , 而是一个逻辑的概念
2、套间表明了位于套间的代码的多线程特性 , 决定了以下几点
a. 代码本身允许单线程调用还是多线程调用
b. 代码创建COM对象拿到的是Proxy还是原始的指针(关于Proxy请参见后面的Proxy一节)
c. 代码调用同一套间的COM对象是通过原始指针 , 不同套间则通过Proxy

STA和MTA 之 COM和套间

文章插图
3. 线程必须属于某个套间 , 这表明了线程本身的多线程特性 , 也就是线程会对COM对象进行多线程的调用还是单线程的调用 。比如 , 一个线程位于STA中 , 那么该线程只适合直接调用支持单线程调用的、同一套间的COM对象 , 其他COM对象则需要通过Proxy来间接调用 , 什么是Proxy后面会讲到 。同时 , 线程所处的套间还决定了创建对象的时候所获得的对象是对象本身还是Proxy 。线程在同一时间内只能属于一个套间或者不属于某个套间 , 但是线程可以在不同时间内属于不同的套间 。典型的例子有 , 线程调用了 , 然后再调用退出套间 , 之后又调用了进入了另外一个套间 , 此外 , 线程临时进入NTA也是一个例子 。下面会讲到 。
4. COM对象也必须属于某个套间 , 同样的这决定了COM对象的多线程特性 , 和上面类似 。COM对象不会从一个套间迁移到另外一个套间 , 如果这个套间被释放 , 那么这个对象也同时被释放 , 这个事实对于STA套间尤为重要 。
5. 跨套间必须要通过Proxy , 这是COM保证套间能够工作的基础 。后面Proxy一节会谈到为什么是这样