首页 > 试题广场 >

谈谈COM的线程模型 。然后讨论进程内外组件的差别。

[问答题]
谈谈COM的线程 模型 。然后 讨论 进程内/外组件的差别。
中文翻译为 公寓 ,有时候为 套间 ,这里就翻译为 公寓 吧,都一个意思,指的就是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,就不会有任何线程访问冲突的问题。《Win32 多线程》侯捷
进程内/外组件的差别是Com组建的一种表现形式:.exe文件,它是进程外组建,dll是进程内组建.
发表于 2017-01-24 00:33:03 回复(0)