关于Delphi-Midas多层开发的系列讨论之二:远程数据模块设置 ( 积分: 0 )

  • 主题发起人 主题发起人 yaxich
  • 开始时间 开始时间
远程数据模块创建时会有一个向导,在向导中需要根据需要设置其实例属性(Instancing)和线程模式(Threading Model)。
一、实例属性(Instancing)
1.Internal:服务程序内部创建实例,客户端的申请服务行为无法创建实例
2.Single Instance:单实例模式,服务程序只能有一个Rmd实例,不同的客户端只能顺序申请服务或启动多个服务程序实例来获取服务
3.Multiple Instance:多实例模式,一个服务程序实例可以创建多个Rmd实例,不同客户端可以应用不同的Rmd实例
二、线程模式(Threading Model)
1.Single:单线程,只有一个Rmd线程,所有客户端只能顺序地得到服务。
2.Apartment:服务程序可以同时有多个Rmd线程,但每个Rmd线程只能服务以单线程模式运行。
3.Free:没有线程限制的模式,没见用过。
4.Both:介于Apartment和Free之间的一种线程模式,没见用过。
5.Neutral:仅对Com+有效,可以使多个客户端同时以多线程模式应用服务器,建议使用,但注意全局变量的保护问题。
 
写完上面的帖子,做了一个测试,发现挺有意思的一个现象:
我创建了一个工程,添加一个Rmd,参数为:ciMultiInstance, tmNeutral,添加一个方法为TestInterface,代码如下:
Var
iStart: Integer;
begin
iStart := GetTickCount;
Sleep(5000);
Result := 'This thread ID is: ' + IntToStr(GetCurrentThreadID) + #13#10 + 'Start at: '+ IntToStr(iStart) + ', ' + 'End at: ' + IntToStr(GetTickCount);
end;
保存运行。
创建另一个工程,为客户端,在窗体上放了一个SocketConnect,一个Label,一个Button,设置SocketConnection连接刚刚创建的服务,Button的OnClick为:
SocketConnection1.Connected := True;
Label1.Caption := SocketConnection1.AppServer.TestInterface;

保存编译完成后直接运行了两个客户端Exe实例(运行两次),迅速地连续点击两个的实例中的Button,发现服务器的确创建了两个Rmd,但是创建了第一个Rmd后执行了TestInterface的调用后才创建第二个Rmd,而且线程为一个线程(奇怪?).
然后将上述Button单击事件中的SocketConnection1.Connected := True;移至另一个按钮的点击事件中,仍然运行两个实例,先分别点击第二个连接按钮,发现服务程序的确创建了两个Rmd,然后再点击两个调用服务程序方法的按钮,发现执行还是顺序进行的,根据返回的执行时间看,的确是顺序的。
请问高手们,这是怎么回事?如何才能使服务程序真正同时处理客户端的请求?请指教!
 
这好几天了,论坛一直上不来,今天终于能上了,大家看看上面到底是怎么回事,如何解决?
 
我先不讨论你现在的程序是否是实现了同时处理客户端的请求。
我觉得你这样的测试不能得出这个结论,因为你点击还是有时间间隔的,你点的再快也有间隔。
 
to twosunsun:
你可以按照我上面说的那样子建一下测试一下,从返回的执行开始与结束时间上就可以发现这个问题了。
 
参数为:ciMultiInstance, tmApartment创建RDM则应该是并发的,我以前测试过确实是并发的,因为TComponentFactory这个类工厂使用了TApartmentThread来创建RDM实例,不过它默认的是tmApartment这种线程模式,所以你换成tmNeutral就不能使用TApartmentThread来创建RDM实例,这时候就是顺序的创建RDM,而不是由TApartmentThread产生一个TApartmentThread线程再由这个线程来创建RDM实例
function TComponentFactory.CreateInstance(const UnkOuter: IUnknown;
const IID: TGUID;
out Obj): HResult;
stdcall;
begin
if not IsLibrary and (ThreadingModel = tmApartment) then
begin
LockServer(True);
try
with TApartmentThread.Create(Self, UnkOuter, IID)do
begin
if WaitForSingleObject(Semaphore, INFINITE) = WAIT_OBJECT_0 then
begin
Result := CreateResult;
if Result <>
S_OK then
Exit;
Result := CoGetInterfaceAndReleaseStream(IStream(ObjStream), IID, Obj);
end else
Result := E_FAIL
end;
finally
LockServer(False);
end;
end else
Result := inherited CreateInstance(UnkOuter, IID, Obj);
end;
如果你要并发,要么就改你的线程模式要么就修改TComponentFactory中的vcl源码或者创建自己的类工厂
 
借地方提下自己的问题,关于远程数据模块建立的
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3001000
麻烦各位帮忙看看
 
to KillAll2004:
刚才我看了一下,的确是这样子的,谢谢,我再好好看看,再找找我程序里的问题。
 
后退
顶部