标题:COM的线程模型


(1)接口与组件

CoInitialize()

CoCreateInstance()

CoUninitialize()

 

(2)代理与残根

(3)自动化与调度接口

自动化是指实现了IDispatch接口的COM组件。而IDispatch接口实现了调度接口(一组函数,Invoke(),GetID())。

VARIANT变量:各种类型的联合,VT:类型,xxVal:值。

类型库:与语言无关,与C++头文件等价的二进制文件,是IDL文件编译后生成的结果。

BSTR:第一个字段4字节ULONG,表示串的字节数。第二个字段为字符串本身,以双字节NULL结束,中间可以嵌入NULL

 

(4)线程模型

公寓(Apartment)有的译文译作"套间"。这个术语抽象的是COM对象的生存空间,你还真的可以想象成公寓,线程就是住在公寓里的人。套间定义了一组对象的逻辑组合,这些对象共享一组并发性和冲入限制。每个COM对象都属于某一个套间,一个套间可以包含多个COM对象。

单线程套间-->一个线程-->序列化访问所拥有的com对象

多线程套间-->多个线程-->直接访问所拥有的com对象(同步需要自己考虑)

 

A.单线程套间STA

Single-threaded Apartments,一个套间只关联一个线程,COM库保证对象只能由这个线程访问(通过对象的接口指针调用其方法),其他线程不得直接访问这个对象(可以间接访问,但最终还是由这个线程访问)

COM库实现了所有调用的同步,因为只有关联线程能访问COM对象。如果有N个调用同时并发,N-1个调用处于阻塞状态。对象的状态(也就是对象的成员变量的值)肯定是正确变化的,不会出现线程访问冲突而导致对象状态错误。

 

B.多线程套间MTA

Multithreaded Apartments,一个套间可以对应多个线程,COM对象可以被多个线程并发访问。所以这个对象的作者必须在自己的代码中实现线程保护、同步工作,保证可以正确改变自己的状态。

 

(5)进程模型

COM 所提供的服务组件对象在实现时有两种进程模型:进程内对象和进程外对象。如果是进程内对象,则它在客户进程空间中运行;如果是进程外对象,则它运行在同机器上的另一个进程空间或者在远程机器的空间。

 

A.进程内服务程序:

服务程序被加载到客户的进程空间,在 Windows 环境下,通常服务程序的代码以动态连接库(DLL)的形式实现。

 

B.本地服务程序:

服务程序与客户程序运行在同一台机器上,服务程序是一个独立的应用程序,通常它是一个 EXE 文件。

C.远程服务程序:

服务程序运行在与客户不同的机器上,它既可以是一个 DLL 模块,也可以是一个 EXE 文件。如果远程服务程序是以 DLL 形式实现的话,则远程机器会创建一个代理进程。

虽然 COM 对象有不同的进程模型,但这种区别对于客户程序来说是透明的,因此客户程序在使用组件对象时可以不管这种区别的存在,只要遵照 COM 规范即可。然而,在实现 COM 对象时,还是应该慎重选择进程模型。进程内模型的优点是效率高,但组件不稳定会引起客户进程崩溃,因此组件可能会危及客户;进程外模型的优点是稳定性好,组件进程不会危及客户程序,一个组件进程可以为多个客户进程提供服务,但进程外组件开销大,而且调用效率相对低一点。

 

(6)COM可重用性

由于 COM 标准是建立在二进制代码级的,因此 COM 对象的可重用性与一般的面向对象语言如 C++ 中对象的重用过程不同,是基于二进制的共享。

对于 COM 对象的客户程序来说,它只是通过接口使用对象提供的服务,它并不知道对象内部的实现过程,因此,组件对象的重用性可建立在组件对象的行为方式上,而不是具体实现上,这是建立重用的关键。

COM 用两种机制实现对象的重用。我们假定有两个 COM 对象,对象1 希望能重用对象2 的功能,我们把对象1 称为外部对象,对象2 称为内部对象。

A.包容方式。

对象1 包含了对象2,当对象1 需要用到对象2 的功能时,它可以简单地把实现交给对象2 来完成,虽然对象1 和对象2 支持同样的接口,但对象1 在实现接口时实际上调用了对象2 的实现。

B.聚合方式。

对象1 只需简单地把对象2 的接口递交给客户即可,对象1 并没有实现对象2 的接口,但它把对象2 的接口也暴露给客户程序,而客户程序并不知道内部对象2 的存在。



看文字不过瘾?点击我,进入周哥教IT视频教学
麦洛科菲长期致力于IT安全技术的推广与普及,我们更专业!我们的学员已经广泛就职于BAT360等各大IT互联网公司。详情请参考我们的 业界反馈 《周哥教IT.C语言深学活用》视频

我们的微信公众号,敬请关注