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 <> nil) and 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的对象

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

DataSnap 2009 系列之三 (生命周期篇)的更多相关文章

  1. Spring源码系列 — Bean生命周期

    前言 上篇文章中介绍了Spring容器的扩展点,这个是在Bean的创建过程之前执行的逻辑.承接扩展点之后,就是Spring容器的另一个核心:Bean的生命周期过程.这个生命周期过程大致经历了一下的几个 ...

  2. React源码剖析系列 - 生命周期的管理艺术

    目前,前端领域中 React 势头正盛,很少能够深入剖析内部实现机制和原理.本系列文章希望通过剖析 React 源码,理解其内部的实现原理,知其然更要知其所以然. 对于 React,其组件生命周期(C ...

  3. Android学习整理之Activity生命周期篇

    一.Activity生命周期说明   Activity的四种状态: ⒈活动状态(Active or Running):也称为运行状态,处于Activity栈顶,在用户界面中最上层,完全能被用户看到,能 ...

  4. 从 0 到 1 实现 React 系列 —— 3.生命周期和 diff 算法

    看源码一个痛处是会陷进理不顺主干的困局中,本系列文章在实现一个 (x)react 的同时理顺 React 框架的主干内容(JSX/虚拟DOM/组件/生命周期/diff算法/setState/ref/. ...

  5. Android 组件系列-----Activity生命周期

    本篇随笔将会深入学习Activity,包括如何定义多个Activity,并设置为默认的Activity.如何从一个Activity跳转到另一个Activity,还有就是详细分析Activity的生命周 ...

  6. React 源码剖析系列 - 生命周期的管理艺术

    目前,前端领域中 React 势头正盛,很少能够深入剖析内部实现机制和原理. 本系列文章 希望通过剖析 React 源码,理解其内部的实现原理,知其然更要知其所以然. 对于 React,其组件生命周期 ...

  7. 浅聊本人学习React的历程——第一篇生命周期篇

    作为一个前端小白,在踏入前端程序猿行业的第三年接触了React,一直对于框架有种恐惧感,可能是对陌生事物的恐惧心里吧,导致自己一直在使用原生JS和JQ作为开发首选,但是在接触了React之后,发现了其 ...

  8. Vue.js系列:生命周期钩子

    开发人员提供了一个Web开发人员可以在Vue.js应用程序的整个生命周期中使用的各种方法的讨论. 生命周期钩子是在Vue对象生命周期的某个阶段执行的已定义方法.从初始化开始到它被破坏时,对象都会遵循不 ...

  9. [spring] -- bean作用域跟生命周期篇

    作用域 singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的. prototype : 每次请求都会创建一个新的 bean 实例. request : 每一次HT ...

随机推荐

  1. 基础14_转义字符和特殊字符ASCII

    一.摘要 PSQL转义字符 二.PLSQL转义字符 PLSQL对应的字符和序号关系 二.PLSQL特殊字符 PLSQL对应的字符和序号关系 1. 转义字符为' '; )||'%'; --A&B ...

  2. 在阿里云主机上基于CentOS用vsftpd搭建FTP服务器

    最近需要在一台阿里云的云服务器上搭建FTP服务器,在这篇博文中分享一下我们根据实际需求进行的一些配置. ftp软件用的是vsftpd. vsftpd是一款在Linux发行版中最受推崇的FTP服务器程序 ...

  3. sharedPreferences的用法

    做软件开发应该都知道,很多软件会有配置文件,里面存放这程序运行当中的各个属性值,由于其配置信息并不多,如果采用数据库来存放并不划算,因为数据库连 接跟操作等耗时大大影响了程序的效率,因此我们使用键值这 ...

  4. ASCIITable: 演示 Arduino 串口输出的进阶功能

    原文地址 - https://www.arduino.cc/en/Tutorial/ASCIITable ASCII字符表 本例展示了高级的串口打印功能,通过本功能可以在Arduino软件(IDE)的 ...

  5. 使用Ninject进行DI(依赖注入)

    Ninject是一个快如闪电.超轻量级的基于.Net平台的依赖注入框架.它能够帮助你把应用程序分离成一个个松耦合.高内聚的模块,然后用一种灵活的方式组装起来.通过使用Ninject配套你的软件架构,那 ...

  6. [源码]String StringBuffer StringBudlider(1String部分)

      String     /** The value is used for character storage. */     private final char value[];  /** Th ...

  7. Access自动编号的初始值设置及重置编号

    项目上需要在Access数据库,发现自动编号的列无法设置初始值和步长,但是可以使用SQL语句来设置它. 方法如下: ALTER TABLE tableName ALTER COLUMN ID COUN ...

  8. Win10 disable 最近打开

    1. 开始菜单 -> Settings -> Personalization -> Start 2. Set "Show most used apps" Off ...

  9. Hadoop_配置_linux下编译eclipse插件

    使用的hadoop版本为hadoop-1.2.1(对应的含源码的安装包为hadoop-1.2.1.tar.gz) 将hadoop和eclipse都解压在home中的用户目录下 /home/chen/h ...

  10. Android基础

    今天学习Android基本环境及基础知识,正确来说是重新温习Android知识,因为初次接触Android开发已经是两年前的事,如今又回到Android开发依然那么熟悉,依然可以让人很兴奋,Andro ...