再论COM的线程模型

前些时间转载了一篇关于COM线程模型的文章,感觉效果还是很一般,我后来又搜集了些资料,打算自己写一篇非常通俗易懂,而又准确的文章,这就是本文。

泛说"COM线程模型":http://blog.csdn.net/guogangj/archive/2007/09/06/1774280.aspx 

Apartment,中文翻译为公寓,有时候为套间,这里就翻译为公寓吧,都一个意思,指的就是COM的线程模式,这个概念很抽象,理解起来比较困难。因为公寓不像Windows内核对象那样有个句柄,并且跟公寓相关的Windows API很少,只有5个:CoInitialize,CoUninitialize,CoInitializeEx,OleInitialize和OleUninitialize,大家都很熟悉了,5个关于COM初始化和反初始化的函数。如何来理解公寓呢?可以这样:1、线程住在公寓中;2、对象住在公寓中。有时候,对象和创建它的线程住在同一个公寓中,有时候不是。这样还是很难理解对吧,但没事,这个先记下来,后面会明白的。

COM只有两种公寓,一种叫单线程公寓(Single-Thread Apartment),简称STA,一种叫多线程公寓(Multi-Thread Apartment),简称MTA,顾名思义,一种只能容纳一个线程,另一种能容纳多个线程。在一个进程中,MTA只有一个,而STA可以有很多。

 

我们在使用COM之前,都应该先初始化COM,怎么初始化?当然是前文提到的那几个函数了,CoInitialize,CoInitializeEx和OleInitialize,那我们是每个程序(进程)初始化一次还是每个线程初始化一次?答案是线程,每个线程初始化一次,这么个初始化,就相当于把这个线程安置在某个公寓中。具体这样的:CoInitialize或OleInitialize把线程放置入STA;CoInitializeEx允许你把线程放置入MTA。从公寓中移除线程的方法是CoUninitialize和OleUninitialize。

 

我们都知道,对象是线程创建的,那对象什么时候跟创建它的线程同一个公寓,什么时候不是同一个公寓呢?前面说了线程所在的公寓类型是由那几个初始化函数所决定,那对象所在什么公寓是由什么决定的呢?这个稍微复杂一点,答案是:由创建它的线程的类型及对象本身的线程属性所决定。线程类型大家都知道啦,就前面提到的由那几个初始化函数决定,那么对象本身线程属性怎么来定呢?答案:注册表里的信息来定。

 

打开注册表编辑器,按照这路径:/HKEY_CLASSES_ROOT/CLSID/{00000010-0000-0010-8000-00AA006D2EA4}/InprocServer32,(这个GUID很奇怪吧,明显不是用工具生成的,微软可有手动填写GUID的特权哦)看看ThreadingModel的值,嗯,没错,是Apartment,这个Apartment就是刚才我所提到的对象本身线程属性,对象本身线程属性一共有四种:Apartment、Both、Free和Single。下面我列个表,一目了然。

 

组件线程属性 |  STA线程                        |  MTA线程

--------------------------------------------------------------------------------------

Apartment    |  同一公寓中,直接访问           |  创建一个STA,用代理访问

Free         |  MTA中,用代理访问              |  MTA,直接访问

Both         |  同一公寓中,直接访问           |  MTA,直接访问

Single       |  主STA中,通过主STA访问

 

备注:第一个以COINIT_APARTMENTTHREADED调用CoInitializeEx()的线程被称作是主STA。

 

例如一个STA线程创建了一个本身线程属性为Free的对象,那该对象存在于MTA中,这个STA线程访问它就得通过代理,当然了,这对程序员来说是透明的,因为这个功能是靠COM的remoting层来实现的。要说和直接访问有什么能体现出来的不同,可能就是通过代理访问会慢一些,毕竟消息需要Marshalling,但这几毫秒的时间差你们地球人是很难感觉出来的(J)。

 

那么很明显了,只要我们把组件类型设置为Apartment,就不会有任何线程访问冲突的问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值