博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DataSnap 2009 系列之三 (生命周期篇)
阅读量:5104 次
发布时间:2019-06-13

本文共 2742 字,大约阅读时间需要 9 分钟。

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的对象

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

附上DEMO源码

转载于:https://www.cnblogs.com/MaxWoods/archive/2011/09/23/2187840.html

你可能感兴趣的文章
Screening technology proved cost effective deal
查看>>
mysql8.0.13下载与安装图文教程
查看>>
Thrift Expected protocol id ffffff82 but got 0
查看>>
【2.2】创建博客文章模型
查看>>
从零开始系列之vue全家桶(1)安装前期准备nodejs+cnpm+webpack+vue-cli+vue-router
查看>>
Jsp抓取页面内容
查看>>
大三上学期软件工程作业之点餐系统(网页版)的一些心得
查看>>
可选参数的函数还可以这样设计!
查看>>
[你必须知道的.NET]第二十一回:认识全面的null
查看>>
Java语言概述
查看>>
关于BOM知识的整理
查看>>
使用word发布博客
查看>>
面向对象的小demo
查看>>
微服务之初了解(一)
查看>>
GDOI DAY1游记
查看>>
收集WebDriver的执行命令和参数信息
查看>>
数据结构与算法(三)-线性表之静态链表
查看>>
mac下的mysql报错:ERROR 1045(28000)和ERROR 2002 (HY000)的解决办法
查看>>
快速幂
查看>>
AIO 开始不定时的抛异常: java.io.IOException: 指定的网络名不再可用
查看>>