COM服务器的伪异步技术及其实现

上传人:l****6 文档编号:38057303 上传时间:2018-04-26 格式:DOC 页数:4 大小:30KB
返回 下载 相关 举报
COM服务器的伪异步技术及其实现_第1页
第1页 / 共4页
COM服务器的伪异步技术及其实现_第2页
第2页 / 共4页
COM服务器的伪异步技术及其实现_第3页
第3页 / 共4页
COM服务器的伪异步技术及其实现_第4页
第4页 / 共4页
亲,该文档总共4页,全部预览完了,如果喜欢就下载吧!
资源描述

《COM服务器的伪异步技术及其实现》由会员分享,可在线阅读,更多相关《COM服务器的伪异步技术及其实现(4页珍藏版)》请在金锄头文库上搜索。

1、1COM 服务器的伪异步技术及其实现摘要:COM 组件技术在 Windows 操作系统中发挥了极其重要的作用,但标准COM 组件技术在实时操作性上不尽完善。作为补充可以用 COM 连接点技术和多线程技术来构造一种伪异步技术, 完成某些前者不能完成的任务。本文详细描述了其实现原理,并根据技术细节提供了作者的解决方案。关键词: COM;异步调用;连接点;接口;STA; MTA 1. COM 异步技术与普通同步执行的 COM 服务器不同,一个提供异步方法调用的 COM 服务器允许客户程序以一种非阻塞的方式来访问它,客户程序可以在等待调用返回的过程中继续进行别的工作,从而提高工作效率。 尤其随着 Wi

2、ndows2000 和 COM+的发布,COM 现在已经完全支持异步方法的调用了,通过 IDL 的定义,由 MIDL 编译器为接口的每个方法实现同步和异步两种独立的调用定义。但是 COM 提供的这种异步方法调用并非尽善尽美:1) 这种技术发布较晚,只在 WIN2000 下被支持,所以用它开发的软件不能在Windows 95 和 Windows NT 平台上运行。2) 客户端使用不便,尽管 COM 通过 MIDL 生成的接口代理(proxy)与存根(stub)完成了大部分为支持异步方法调用所做的工作,客户端仍需要完成系列繁琐的细节工作。3) 无论客户端还是服务器端都需要聚合由 COM 提供的对象

3、,方法调用方式也有别于标准同步调用,因而不适用于标准 ACTIVEX 控件的编写,而 ACTIVEX 控件实质上是一种特殊的 COM 服务器。2由于上述一系列缺陷,往往需要一种替代解决办法,通常可以用一些基本的 COM技术来构造一种伪异步技术。2. COM 应用这种伪异步技术是通过接口回调(interface callback)的方法来实现的,它基于两项关键的 COM 技术: 连接点(Connection point)技术和 COM 多线程(Multithread)技术。连接点技术的基础是 COM 的出接口(outgoing interface)。出接口与普通的接口不一样,它由 COM 服务器

4、端进行定义,但却由用户程序来实现(此实现对象被称为接收器 sink),并把接口指针告诉给 COM 服务器。由于出接口是在服务器的类型库中定义, 所以 COM 服务器可以很方便的利用此接口指针与客户进行通讯。但直接使用出接口,客户程序和 COM 服务器都需要出接口有一定的了解,为此COM 又提供了连接点技术(可连接对象),如图:COM 提供的可连接对象,通过 IConnectionPointContainer 接口管理所有的出接口。对应于每个出接口,可连接对象管理一个连接点对象,每一个连接点对象实现了IConnectionPoint 接口,客户通过连接点对象建立接收器与可连接对象的连接,且通过两

5、个枚举器的引入,使得可连接对象支持多个出接口,而每个出接口支持多个与接收器的连接。明显,连接点技术的实质是对出接口的一种封装。通过使用连接点技术,COM 服务器可以用一种非常常规的方法描述它的引出接口,并为客户程序提供了一种标准的方法来实现这些接口,对于实现服务器组件的标准化非常方便,也有利于客户程序的独立开发,符合中间件开发的原则。 COM 多线程管理相当复杂,要实现多线程,应对 COM 的线程模型有深入的了解。3COM 支持两种线程模型:单线程单元(STA,Single-Threaded Apartment)和多线程单元(MTA,MultiThreaded Apartment)。如图所示:

6、单元是一种抽象的概念,定义了一组对象的逻辑集合,这些对象共享同一组并发性和重入限制,每个 COM 对象都只能属于某一个单元。STA 只能包含一个线程(单元线程),与 32 位 Windows 平台上的用户界面(UI)线程相似,单元线程拥有一个隐藏的窗口,所有对此线程中服务器组件方法的调用都被 COM 转化为消息(message),通过消息循环进行消息分发,并调用窗口过程保证调用到 COM 对象的成员函数中;而每个 MTA 可以包含多个线程(自由线程),自由线程相似于Windows 平台的工作(Work)线程,不带消息分发,可以直接使用。每个进程只能有一个 MTA,但是可以于有任意多个 STA,

7、每一个使用 COM 的线程必须通过调用 CoInitialize(0)来新建一个 STA,或者通过调用CoInitializeEx(0,COINT_MULTITHREAD)来创建或加入一个 MTA,否则这个线程将出错。服务器组件实体存在于线程中,要么处于 MTA 中,要么处在 STA 中,别无选择。遵守如下规则:跨单元的接口指针传递需要调度,否则指针无效。3. 构造伪异步 COM 服务器3.1 伪异步 COM 服务器总体框架伪异步调用的实质是客户程序将一个自己所实现的接收器指针传递到 COM 服务器,当服务器的接口受到客户程序调用的时候将产生新的线程来实现功能任务,而客户程序的调用结束返回,新

8、线程将在任务完成后通过传入的接口指针回调到客户程序,以通知客户程序当前调用服务的消息和结果,从而在客户程序和服务器之间产生一种对等关系。服务器和客户程序异步协商过程如下:1) COM 实现一个服务器组件对象,它要么处在 STA 中,要么处在 MTA 中。42) 客户程序通过 COM 服务器的公开接口查询 IConnectionPointContainer 接口,客户查询成功就表明服务器支持连接点。3) 查询成功,客户程序使用上面接口的 FindConnectionPoint()方法来定位特定的出接口;或者用 EnumConnectionPoints()方法枚举所有连接点,再进行查询定位。这样客

9、户程序可以获得一个 IConnectionPoint 接口,并通过它建立与服务器的连接。4) 定位成功,则由客户端实现这个出接口,这里的接口实现也即接收器(Sink)。5) 客户程序通过 IConnectionPoint:Advise()方法将一个指向接收器的一个出接口指针传递给服务器。连接被建立。6) COM 服务器收到调用请求,创建新线程,并由新线程通过这个收到的出接口指针进行回调(callback)操作,将通知或消息反馈到接收器,从而完成一次异步调用。这是一种非常常规的方法,为客户程序提供了一个标准的方法来实现这些接口,而且 MFC(微软基本类库)和 ATL(活动模板类库)都对连接点技术

10、提供了很好的支持,使用方便。当然也能在服务器组件中直接使用出接口,从而省去出于标准化目的而对出接口进行的封装。这样的好处是服务器组件直观、高效,可以减少额外的开销,但是它不能为客户程序提供一个标准的方法来实现出接口,所以建议只在服务器和客户端配合开发,双方均了解出接口,且接口较为简单的情况下使用。3.2 MTA 中的 COM 服务器如果 COM 服务器组件处在一个多线程单元(MTA)里面的,要实现异步回调非常容易,只要新生成的线程通过 CoInitializeEx(0,COINT_MULTITHREAD)也加入了同一个 MTA,那么 COM 服务器就可以简单地将接收器传入的出接口指针传递给这个

11、新线程,新线程可以使用这个指针直接进行回调操作。原因很简单,出接口5的指针传递并没有跨单元。如果新生成的线程通过 CoInitialize (0)创建了一个新的 STA,我们也可以作同样处理。在此情况下,跨单元的接口指针传递的确需要进行调度,但是 COM 相当聪明,在此情况下它能自动完成指针的调度。当然了,调度必然影响组件的效率,不管我们是手动调度或者是 COM 进行的自动调度。在服务器的开发中引入 MTA,通常是为了追求高效率,提供组件对并行性的支持。相应的,必须对服务器对象的成员函数进行同步处理,保证多个线程调用不会发生冲突,也就是说服务器组件必须是在各方面都是线程安全的,全局数据也必须要

12、受到保护。3.3 STA 中的 COM 服务器COM 服务器组件如果被建立在一个单线程单元(STA)里面的,情况就不同了,因为 STA 中只存在一个线程, 要实现异步回调,必然要涉及到出接口指针的跨单元使用。通常有两种解决方案:(1)由 COM 服务器组件把出接口指针调度到新的线程中去,这个过程在通常情况下是由服务器组件的开发人员手工进行调度, COM 提供了两个标准的函数,服务器组件使用函数 CoMarshallInterThreadInterfaceInStream(IID_ICallBack,m_pCallBack,pStream) 将出接口指针调度到一个流(stream)中去,而在需要

13、执行回调的新线程里使用 COM 所提供的 CoGetInterfaceAndReleaseStream(pStream, IID_ICallBack, (void *)pCallBack)函数将流里的出接口指针 pCallBack 取出来。通过这个调度过程,COM 为指针在两端建立了代理和存根,我们就可以在新线程里直接使用这个指针进行回调操作了。这是一个普遍的用法, 但是指针的调度是一个开销很大的过程,所以它的效率不高。(2)我们还可以采用另外一种替代方法:新线程向服务器所在线程发送的窗口消息,由 COM 服务器组件实现回调函数(使用出接口指针)来响应这个消息。这个过程6主要是利用消息循环,让

14、 STA 中的窗口过程保证调用到 COM 对象相应的回调函数中去, 新线程可以避免对出接口指针的直接操作。由于避免了指针的跨单元传递,我们就可以节省跨单元调度所需要的开销,效率非常高。在很多时候这甚至是唯一的方法,在 ATL(活动模板库)中使用连接点技术非常方便,因为 ATL 通过连接点向导为回调提供了一个连接代理,对回调过程进行了很好的封装。但是出接口指针被完全封装到了触发(fire)函数中,要跨单元传递出接口指针就非常困难,所以通过消息来触发回调就成了最好的选择。但是应强调一点,STA 里线程必须要实现自己的消息循环机制,能够分发消息,否则对 STA 中组件方法的任何调用都将被挂起(han

15、g)。所以用 MFC 来实现一个存在于 STA 中的 COM 服务器是一个很坏的选择,因为 MFC 中 STA 的线程(类似于工作线程)是不具有消息循环的。采用 STA 开发 COM 服务器虽然复杂,但优点明显。STA 中的单元线程拥有隐藏的窗口,所有对此线程中服务器组件方法的调用都被 COM 转化为消息(message),由窗口过程保证调用到 COM 对象的成员函数中。由于消息总按照一定顺序执行,所以不需要进行同步处理,这也是 STA 模型的最大优点-由 COM 来处理多数线程同步方面的细节问题。如果并不太关心并行性,而更看重组件的功能,那么就可以引入单线程单元(STA)来设计服务器组件。4

16、. 结论要实现一个伪异步工作的 COM 服务器,必须对连接点技术和 COM 线程模型进行合理的组合使用,尤其线程模型的选择更是我们实现高效 COM 服务器的关键。此外,作者个人推荐使用 ATL 来开发这样一个服务器组件,因为它灵活,高效,对 COM 的各项技术均提供了极好的支持,尤其在对 COM 线程模型的支持方面,是 MFC 所不能比拟的。7参考文献1Tom Armstrong 等 (著),董梁 等(译), ATL 开发指南M ,北京:电子工业出版社2潘爱民,COM 原理与应用M , 北京:清华大学出版社3Martin Gudgin(著)宋亚男(译),IDL 精髓M , 北京:中国电力出版社4MSDN(2001),Eight Lessons from the COM School of Hard KnocksC 6MSDN(2001)/Q15077,Descriptions and Workings of OLE Threading ModelsC

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 学术论文 > 其它学术论文

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号