摘要:本文探讨了多线程COM服务器的原理,然后详细介绍利用DELPHI建立多线程COM服务器的方法和步骤,并给出了相应测试实例。
关键词:组件对象模型(COM)、单线程单元模式(STA)、应用程序服务器
本文从实践的角度,详细介绍了在delphi中建立多线程Apartment COM服务器的方法和步骤。有关线程和COM技术的详细内容,请读者参考有关书籍。为便于理解,这里对本文涉及的内容作简要说明:
文中的范例是这样的,假设有一个应用程序服务器,它提供一个方法FooStatus,这个方法需要花3秒的时间来完成它的工作。现在有两个以上客户端应用程序来调用它(本文取两个),且每个客户端又以不同的方式均要调用这个方法3次。那么,总共需要化多少时间完成?如何使执行的效率最好?这是在开发一个多层应用系统时,程序员必须考虑的问题,应该说最理想的状态是总共所化时间在3至5秒之间(假设两个客户端开始执行的时间间隔足够短)。执行情况如图1所示。
图1 客户端应用程序与应用程序服务器建立相对的线程服务对方
也就是说,只要我们能开发出多线程的客户端应用程序和多线程的应用程序服务器,就能实现这种执行效率良好的应用系统。为此必须首先保证应用程序服务器是多线程Apartment模式,这就是本文所要解决的问题。
现在就让我们着手来创建这个系统,开始奇妙的COM之旅。为了调试和测试的方便,笔者在单机上实现并作了相应的测试。在硬盘上建立一个文件夹,取名为statest,在该文件夹内再建立两个子文件夹,分别取名为staserver和staclient。staserver中存放服务端应用程序,staclient中存放客户端应用程序。
一、建立com服务端
1、建立服务端应用程序
首先在Delphi的集成环境中建立服务端应用程序。点击File|New菜单下的New Application选项建立Delphi应用程序。此时Delphi会产生一个空白的窗体以及初始化程序单元,点击File|Save All,在出现的保存对话框中设置好保存路径,即将文件存放在staserver目录中,并将程序单元文件以serverunit1为名保存,类似地将项目文件以staserverpro为名保存。
为更形象地看到客户程序访问服务器的情况,设计应用程序服务器主窗体如图2示,在主窗体上放置一个Tlable标签,将其Caption属性设为“Automation应用程序服务器”,而将主窗体Caption属性设为“Automation Server”。
图2 Automation服务器窗体
2、建立automation对象
点击File|New菜单下的other选项,弹出New Items窗口,选择Activex页,选中Automation Object选项,点击OK按钮。当Delphi显示Automation Object Wizard对话框时,请按图3所示设置信息,将CoClass Name设为staobject,线程模型设定为Apartment,而且允许有多个客户端应用程序同时使用它,点击OK按钮。
图3 Atuomation 对象设置对话框
此时Delph会自动产生Type Library编辑器,我们在其中加入一个方法FooStatus,请按如图4所示顺序进行设置。
图4 接口方法的声明
这个方法主要实现在接受客户的调用后,延迟若干秒后回传一个结果字符串。在这个回传的字符串中会叙述是那一个应用服务器的线程服务了客户端对于FooStatus的调用,它的起始时间及结束时间。FooStatus的程序代码如下:
procedure Tstaobject.FooStatus(delay: SYSINT; var sResult: WideString);
var
istarttime,iendtime:integer;
//
开始时间,结束时间
begin
randomize;
istarttime:=gettickcount;
//
取得目前系统时间,作为起始时间
while (gettickcount - istarttime< delay) do
//
延时
begin
;
end;
iendtime:=gettickcount;
//
取得目前系统时间,作为结束时间
sresult:=format('服务花了%s秒在服务器线程%d开始时间是%d结束时间是%d', [floattostr(delay/1000.0),getcurrentthreadid,istarttime,iendtime]);
//
服务器执行状态
end;
单元文件uses部分的内容:
uses
ComObj, ActiveX, staserverpro_TLB, StdVcl,
Windows, Classes,Dialogs,Messages, SysUtils, Controls,StdCtrls;
保存文件,将此单元文件以STAObjectImpl为名保存。然后运行程序,注册该COM服务器。
至此,我们已经建立了COM服务端,但读者若读过李维的《Delphi 5.x分布式多层应用系统篇》一书想必都知道这个COM服务器目前还事实上是单线程的,原因就是对于Apartment线程模式而言,“一个应用程序服务器可以有许多不同的Apartment。而在每一个Apartment之中可以有许多的COM对象。但在任何时间,在每一个Apartment之中只能有一个线程在执行。这个意思是说,每一个Apartment在同一时间只能服务一个客户端的调用”。“所以如果一个应用程序服务器虽然是使用Apartment线程模式,但是如果应用程序服务器只建立一个Apartment线程的话,那么它仍然一次只能服务一个客户端”
[1]。叙述得非常精采。我们现在来建立客户端,看看到底是怎么回事。
二、建立客户端
1、建立客户端应用程序
为了便于调试,我们将应用程序服务器和客户端应用程序置于同一个项目组(Project Group)中。为此,在保持打开服务端编辑环境的情况下,点击View|Project Manager菜单,在弹出的Project Manager窗口中点击上方的New按钮,如图5所示,并且选择建立一个新的应用程序。
图5 在工程管理窗口中建立一个新的工程作为客户端应用程序
点击File|Save All菜单,在出现的保存对话框中设置好保存路径,即将文件保存在staclient目录中,将程序单元文件以clientunit1为名保存,将项目文件以staclientpro为名保存,将项目组以statestprogroup为名保存。
在客户端主窗体上放置一个Tmemo控件和一个Tbotton控件,效果如图6所示。
图6 客户端窗体
2、导入类型库
客户端应用程序需要用到前面的类型库,点击Project|Import Type Library打开导入类型库对话框,如图7所示。
图7 导入类型库对话框
在导入类型库对话框的上半部分显示的是已经在Windows系统中注册的所有类型库,图9中选中的就是本文所做的类型库,它的类名是Tstaobject。选中了这个列出的类型库后,单击Creat
|