• DataSnap 2009 系列之三 (生命周期篇)


    DataSnap 2009 系列之三 (生命周期篇)

    DataSnap 2009的服务器对象的生命周期依赖于DSServerClass组件的设置

    当DSServer启动时从DSServerClass组件读取LifeCycle属性的值

    注意:LifeCycle的值由于在启动时就已经读取 启动后再修改LifeCycle的值将没有任何效果

    LifeCycle属性的值可以是以下三种字符串之一

    1.Session

    该选项为默认设置

    每个连接都会建立一个独立的服务器对象为客户端提供服务,服务器对象在连接关闭后释放

    因此多个客户端访问的是不同的服务器对象,是线程安全的

    2.Invocation

    对于每次服务端方法调用建立一个独立的服务器对象为客户端提供服务,服务器对象在调用结束后释放

    这个同样也是线程安全的

    但是每次调用都创建和释放服务器对象对于频繁调用的系统影响很大,如果把服务端对象用对象池管理配合此种方式将是个非常不错的解决方案

    3.Server

    所有的客户端使用同一个服务端对象,也就是该对象是单例的

    需要开发人员自己来进行同步的控制,不是线程安全的

     

    在服务端对象创建和释放时将触发DSServerClass的两个重要的事件OnCreateInstance和OnDestroyInstance

    在这里我们可以使用自定义创建和释放服务器对象 同样我们可以用于服务端对象池

     

    下面我们把上一次的DEMO稍微改动下来观察下服务端对象的生命周期

    我们先将DSServer组件的AutoStart设置为False 然后拖上两个Button分别完成Start和Stop的调用

    复制代码
    procedure TMainForm.StartClick(Sender: TObject);
    begin
      DSServer.Start;
    end;

    procedure TMainForm.StopClick(Sender: TObject);
    begin
      DSServer.Stop;
    end;
    复制代码

     

    在OnGetClass中记录服务启动时使用的生命周期

    复制代码
    procedure TMainForm.DSServerClassGetClass(DSServerClass: TDSServerClass;
      
    var PersistentClass: TPersistentClass);
    begin
      DSServerClass.LifeCycle :
    = LifeCycles.Items.Strings[LifeCycles.ItemIndex];
      LogMessage(Memo, 
    '生命周期:' + DSServerClass.LifeCycle);
      PersistentClass :
    = TSM;
    end;
    复制代码

    LifeCycles是一个TRadioGroup存放了生命周期使用的三个字符串

     

    最后在OnCreateInstance和OnDestroyInstance事件中记录服务器对象的创建和释放

    复制代码
    procedure TMainForm.DSServerClassCreateInstance(
      DSCreateInstanceEventObject: TDSCreateInstanceEventObject);
    begin
      LogMessage(Memo, 
    '服务端对象创建');
    end;

    procedure TMainForm.DSServerClassDestroyInstance(
      DSDestroyInstanceEventObject: TDSDestroyInstanceEventObject);
    begin
      LogMessage(Memo, 
    '服务端对象释放');
      
    //DSDestroyInstanceEventObject.ServerClassInstance.Free;
    end;
    复制代码

     

    效果图

    通过Demo我们可以明显的看出三种生命周期的区别 注意切换生命周期需要先停止服务器再启动

     

    但是在我们使用Invocation的时候 会造成内存泄露

    打开服务端的ReportMemoryLeaksOnShutdown 调用了两次方法后关闭服务端可以看到如下提示

    可以看到服务端对象并没有释放

    这里需要我们通过在OnDestroyInstance手动释放

    DSDestroyInstanceEventObject.ServerClassInstance.Free;

    但是我们会发现内存泄露依然存在TDSProviderDataModuleAdapter依然没有释放

    这是由于DataSnap2009中继承自TProviderDataModule的类都使用了适配器模式来支持旧的IAppServer接口

    在服务端对象创建的过程TDSServerClass.CreateInstance中我们可以看到

    if (Instance <> niland Instance.InheritsFrom(TProviderDataModule) then
      CreateInstanceEventObject.ServerClassInstance :
    = TDSProviderDataModuleAdapter.Create(Instance);

     

    因此在服务端释放的TDSServerClass.DestroyInstance中需要释放TDSProviderDataModuleAdapter对象

    复制代码
        if DestroyInstanceEventObject.ServerClassInstance is TDSProviderDataModuleAdapter then
        
    begin
          Adapter :
    = DestroyInstanceEventObject.ServerClassInstance as TDSProviderDataModuleAdapter;
          DestroyInstanceEventObject.ServerClassInstance :
    = Adapter.FProviderDataModule;
          Adapter.FProviderDataModule :
    = nil;
        
    end else
          Adapter :
    = nil;
    复制代码

     

    当使用Invocation生命周期时 传递的ServerClassInstance并不是TDSProviderDataModuleAdapter的对象

    所以尽管我们手动释放了我们的服务端对象 适配器对象任然造成了内存泄露

  • 相关阅读:
    工作需求----表单多选框checkbox交互
    工作需求——JQ小效果分享下
    JQ返回顶部代码分享~~~~
    css 分享之background-attachment 属性
    CSS3学习之分享下transition属性
    css 伪元素分享!!!
    phpcm v9 任意调用分页/phpcm v9首页调用分页不起作用或者乱码
    facebook分享不能显示图片链接问题
    Fatal error: Uncaught SoapFault exception:解决办法
    VUE项目 启动提示 npn ERRT nissing script: dev解决办法
  • 原文地址:https://www.cnblogs.com/s502/p/3237536.html
Copyright © 2020-2023  润新知