constructor Create(ADBXConnection: TDBXConnection); overload; constructor Create(ADBXConnection: TDBXConnection; AInstanceOwner: Boolean); overload;后面的AInstanceOwner参数,挺重要,理解这个,对于避免内存泄漏有很大好处。
默 认情况下,我们使用Create来创建ServerMethodClient,也就AInstanceOwner为true了,也就是所有进入 TServerMethods1Client类方法的参数,都被ServerMethodClient给来释放。我觉得EMBT推荐使用 AInstanceOwner=True。
DATASNP如何释放内存,请看代码
客户端
procedure TDBXCommand.CommandExecuting; begin if Assigned(FFreeOnCloseList) then FreeOnExecuteObjects;//这里释放 Open; CloseReader; if (FParameters <> nil) and (FParameters.Count > 0) then begin if not FPrepared then Prepare; SetParameters; end; end;也就是说,对每个DBXCommand,每次执行前都会清理上一回留下的垃圾。当然最后的垃圾肯定要等到DBXCommand.Close时才去清理了。
对于function(a: TA, out b: TB): TA这样的调用
AInstanceOwner为true时,a, b, 以及返回值result我们都不用去自己Free。尤其要注意入口参数a,可能进去执行后立刻被Free(需要被Marshal的类),也可能是等到下次Call时被Free(比如TStream)。
反之,则都需要自己去free。但是TDBXCallback,是个例外,就算AInstanceOwner为False,也不能自己Free。
服务器端
procedure TDSMethodValues.AssignParameterValues( Parameters: TDBXParameterArray); begin ClearReferenceParameters; //这里清理 if Length(FMethodValues) <> Length(Parameters) then begin SetLength(FMethodValues, Length(Parameters)); SetLength(FAllocatedObjects, Length(Parameters)); end;也是一样的,每回清理前一回留下的垃圾,最后的也是客户端调用DBXCommand.Close时服务器收到"command_close"时被清理,当然服务器自己关闭DBXCommand时也会清理的。
从这个规则,也能看出,客户端,如果要多线程访问服务器,要么访问服务器时聚集到一起,用关键区或者信号量控制同时只有一个线程能上服务器,要么起多个连接。以避免A线程正读的欢呢,B线程就去Call同样的ServerMethod了,把返回结果给Free了。
最后读读EMBT的帖子吧
没有评论:
发表评论