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中我们可以看到
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 系列之三 (生命周期篇)的更多相关文章
- Spring源码系列 — Bean生命周期
前言 上篇文章中介绍了Spring容器的扩展点,这个是在Bean的创建过程之前执行的逻辑.承接扩展点之后,就是Spring容器的另一个核心:Bean的生命周期过程.这个生命周期过程大致经历了一下的几个 ...
- React源码剖析系列 - 生命周期的管理艺术
目前,前端领域中 React 势头正盛,很少能够深入剖析内部实现机制和原理.本系列文章希望通过剖析 React 源码,理解其内部的实现原理,知其然更要知其所以然. 对于 React,其组件生命周期(C ...
- Android学习整理之Activity生命周期篇
一.Activity生命周期说明 Activity的四种状态: ⒈活动状态(Active or Running):也称为运行状态,处于Activity栈顶,在用户界面中最上层,完全能被用户看到,能 ...
- 从 0 到 1 实现 React 系列 —— 3.生命周期和 diff 算法
看源码一个痛处是会陷进理不顺主干的困局中,本系列文章在实现一个 (x)react 的同时理顺 React 框架的主干内容(JSX/虚拟DOM/组件/生命周期/diff算法/setState/ref/. ...
- Android 组件系列-----Activity生命周期
本篇随笔将会深入学习Activity,包括如何定义多个Activity,并设置为默认的Activity.如何从一个Activity跳转到另一个Activity,还有就是详细分析Activity的生命周 ...
- React 源码剖析系列 - 生命周期的管理艺术
目前,前端领域中 React 势头正盛,很少能够深入剖析内部实现机制和原理. 本系列文章 希望通过剖析 React 源码,理解其内部的实现原理,知其然更要知其所以然. 对于 React,其组件生命周期 ...
- 浅聊本人学习React的历程——第一篇生命周期篇
作为一个前端小白,在踏入前端程序猿行业的第三年接触了React,一直对于框架有种恐惧感,可能是对陌生事物的恐惧心里吧,导致自己一直在使用原生JS和JQ作为开发首选,但是在接触了React之后,发现了其 ...
- Vue.js系列:生命周期钩子
开发人员提供了一个Web开发人员可以在Vue.js应用程序的整个生命周期中使用的各种方法的讨论. 生命周期钩子是在Vue对象生命周期的某个阶段执行的已定义方法.从初始化开始到它被破坏时,对象都会遵循不 ...
- [spring] -- bean作用域跟生命周期篇
作用域 singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的. prototype : 每次请求都会创建一个新的 bean 实例. request : 每一次HT ...
随机推荐
- Spark BlockManager的通信及内存占用分析(源码阅读九)
之前阅读也有总结过Block的RPC服务是通过NettyBlockRpcServer提供打开,即下载Block文件的功能.然后在启动jbo的时候由Driver上的BlockManagerMaster对 ...
- C#扇形的绘制与Hittest交互、图种制作
C# 扇区的绘制与交互 哪位大神的杰作,代码里有,我就不废话了.源码下载方式如下. 注:将下面的图下载后,另存为.rar就可以看到图片中隐藏的代码程序了. 图种的制作 图种的目的在于隐藏文件.使得外人 ...
- c++虚函数调用及使用
#include <iostream> using namespace std; class A { public: ; }; class B: public A { public: ; ...
- angular(3)服务 --注入---自定义模块--单页面应用
ng内部,一旦发生值改变操作,如$scope.m=x,就会自动轮询$digest队列,触发指定的$watch,调用其回调函数,然后修改dom树. 干货:https://github.com/xufei ...
- Disruptor 极速体验
已经不记得最早接触到 Disruptor 是什么时候了,只记得发现它的时候它是以具有闪电般的速度被介绍的.于是在脑子里, Disruptor 和"闪电"一词关联了起来,然而却一直没 ...
- oracle补丁升级
PSU的全称是Patch Set Update,Oracle对于其产品每个季度发行一次的补丁包,包含了bug的修复.Oracle选取被用户下载数量多,且被验证过具有较低风险的补丁放入到每个季度的PSU ...
- AIX上增加逻辑卷时报错误0516-787 extendlv: Maximum allocation for logical volume
AIX上增加逻辑卷时报错误0516-787 extendlv: Maximum allocation for logical volume jdelv02 is 512. 在往aix使用chfs -a ...
- mysql成绩排名
关于mysql成绩排名,网上大部分只是order by简单排序,忽略了成绩相同并列名次的问题. 定义了一个表score结构为:
- python download
今天下载 python3 , 从官网下 速度 平均 十几K,网上 搜了下.提供的下载地址 几乎都是 官网的. 于是 下了个 百度同步盘,做 公开分享. 提供给 大家下载,速度 有 300 多K,提高了 ...
- pthon在Notepad++中执行方式
使用 Notepad++ 编辑运行 Python 程序 Notepad++是一个开源的文本编辑器,功能强大而且使用方便.编辑和调试 Python 程序使用什么编辑器或者 IDE不同人有 ...