2011年10月8日星期六

datasnap的初步 对象的销毁

TServerMethods1Client继承自TDSAdminClient,这个类的构造函数
    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的帖子

没有评论:

发表评论