任务(多线程并行)TFDMemTable内存表传参方式调用服务器返回的TDataSet
任务(多线程并行)TFDMemTable内存表传参方式调用服务器返回的TDataSet
服务器端:
function TServerMethods1.getTFDDataSet
( const pSql,pSelectKey:string ):TDataSet;
var iSql,iSelectKey:string;
var FDQry1:TFDQuery; FDCon1:TFDConnection;
ACds:TClientDataSet; TempProvider:TDataSetProvider;
// FDMemTable:TFDMemTable; //内存表处理也可
var Msg:TJSONValue; ifBroadcast:Boolean;
var FieldDefsCount:Integer; AtestCount:Integer;
begin
iSql:=pSql; iSelectKey:=pSelectKey;
//用内存表中转返回值回调的赋值时间:
//FDMemTable:=TFDMemTable.Create(nil);
ACds:=TClientDataSet.Create(nil); //TClientDataSet
if FDConGlobal.Connected=false then
FDConGlobal.Connected:=true;
// FDCon1:=TFDConnection.Create(nil); //FDCon此连接用完后不能释放只能断开交给连接管理员Pooling管理
// FDCon1.ConnectionDefName:='MSSQL';
FDQry1:=TFDQuery.Create(FDConGlobal); //FDQuery此连接用完后不能释放只能断开交给连接管理员Pooling管理
FDQry1.Connection:=FDConGlobal;//:交给全局连接池,不要动态生成连接,否则客户端连续请求时,会提示Socket的IP和Address已经被占用啦
try
FDQry1.FetchOptions.Mode:=fmAll;//FDQry1.FetchOptions.RecordCountMode:=cmTotal;//cmVisible
FDQry1.FetchOptions.RecordCountMode:=cmFetched;
FDQry1.FetchOptions.RowsetSize:=999999;
FDQry1.FetchOptions.RecsMax:=-1;
FDQry1.FetchOptions.RecsSkip:=-1;
// FDMemTable.FetchOptions.Mode:=fmAll;//FDMemTable.FetchOptions.RecordCountMode:=cmTotal; //cmVisible
// FDMemTable.FetchOptions.RecordCountMode:=cmFetched;
// FDMemTable.FetchOptions.RowsetSize:=999999;
// FDMemTable.FetchOptions.RecsMax:=-1;
// FDMemTable.FetchOptions.RecsSkip:=-1;
FDQry1.close; FDQry1.DisableControls;
FDQry1.SQL.Text:=iSql; FDQry1.EnableControls; //' select module_name,Report_name,com_id from ctl04000 ';
FDQry1.Active:=true;//FDQry1.Open(iSql);
FDQry1.First;
while FDQry1.State=dsInactive do sleep(0);
if FDQry1.Active=true then FDQry1.First;
ACds.FieldDefs:=FDQry1.FieldDefs;
//Memo1.Lines.Add('TClientDataSet字段数:'+IntToStr(ACds.FieldDefs.Count));
TempProvider:=TDataSetProvider.Create(nil);
TempProvider.DataSet:=FDQry1; //:TClientDataSet的数据提供者
ACds.Data:=TempProvider.Data;
// if FDMemTable.State<>dsInactive then FDMemTable.Close;//FDMemTable.Active:=false;
// FDMemTable.AppendData(FDQry1);
// MainServerForm.Memo_Errors.Lines.Add('记录数:'+IntToStr(FDMemTable.RecordCount));
// for AtestCount := 0 to FDMemTable.FieldDefs.Count-1 do
// MainServerForm.Memo_Errors.Lines.Add('字段数:'+FDMemTable.FieldDefs[AtestCount].Name);
// Result:=FDMemTable;//:回调客户端请求
while ACds.State=dsInactive do sleep(0);
if ACds.Active=true then ACds.First;
MainServerForm.Memo_Errors.Lines.Add('记录数:'+IntToStr(ACds.RecordCount));
for AtestCount := 0 to ACds.FieldDefs.Count-1 do
MainServerForm.Memo_Errors.Lines.Add('字段数:'+ACds.FieldDefs[AtestCount].Name);
Result:=ACds;
finally
//ACds: TClientDataSet和TFDMemTable本质一样,都是内存缓存的,不需要释放,函数调用完毕后会自动释放,
//若释放啦,因为返回需要时间,返回值会出问题
try
//if ( (testTFDDataSet_ifFinished.Trim).Indexof('OK')>=0 ) then
//:上面的跟踪判断会滞后,要等响应完之后,不要用
FDQry1.Active:=false; while FDQry1.State<>dsInactive do sleep(0);
FreeAndNil(FDQry1);
FreeAndNil(TempProvider);//:TClientDataSet的数据提供者
MainServerForm.Memo_Errors.Lines.Add('组件FDQry1释放成功!');
//FDCon1.Close; //:【数据库连接取完数后】可以断开连接,连接不要释放,交给连接池自动管理。
//:跟DSServerClass1.LifeCycle生命周期管理有关!【用完后】才能释放:需要下面搞清楚什么是【用完后】
except
MainServerForm.Memo_Errors.Lines.Add('释放出错啦');
end;
end;
end;
客户端:
1、公用代码单元(传入TFDMemTable内存表参数调用服务端):
function getFDMemT_SrvMethGetTFDDataSet(
pSql: string; pSelectKey: string;
var paramFDMemTable: TFDMemTable):Boolean;
var AFDMemTable:TFDMemTable;
ATDataSet:TDataSet; FieldDefsCircle:Integer;
begin
AFDMemTable:=TFDMemTable.Create(nil); //:形参,产生和释放很重要
AFDMemTable.FetchOptions.Mode:=fmAll;
AFDMemTable.FetchOptions.RecordCountMode:=cmFetched;
AFDMemTable.FetchOptions.RowsetSize:=9999999;
AFDMemTable.FetchOptions.RecsMax:=-1;
AFDMemTable.FetchOptions.RecsSkip:=-1;
if AFDMemTable.State<>dsInactive then
begin
AFDMemTable.Close;
end;
try
try
//调用服务器上方法:
//ATDataSet:直接赋值,既不要创建也不要释放:
//if not Assigned(ATDataSet) then //多核多处理器环境,单核环境或win32应用不存在此问题!
ATDataSet:=( ClientModule1.ServerMethods1Client.getTFDDataSet(pSql, pSelectKey) );
while ATDataSet.State=dsInactive do sleep(0); //:确认返回了数据
if ATDataSet.Active=true then
begin
ATDataSet.First;
// 以下:形参 获取 从服务器返回的ATDataSet:TDataSet数据集数据
AFDMemTable.FieldDefs.Clear;
AFDMemTable.FieldDefs:=ATDataSet.FieldDefs;
AFDMemTable.Open;
while not (ATDataSet.Eof) do
begin
AFDMemTable.Append;
for FieldDefsCircle := 0 to AFDMemTable.FieldDefs.Count-1 do
begin
AFDMemTable.FieldByName(AFDMemTable.FieldDefs[FieldDefsCircle].Name).Value:=ATDataSet.FieldByName(AFDMemTable.FieldDefs[FieldDefsCircle].Name).Value;
end;
AFDMemTable.Post;
ATDataSet.Next;
end;
//Memo1.Lines.Add('TFDMemTable记录数:'+IntToStr(AFDMemTable.RecordCount));
AFDMemTable.First;
AFDMemTable.IndexesActive:=true;
AFDMemTable.Active:=true; //:形参 激活数据,以便下面传递给 实参
end;
paramFDMemTable.CloneCursor(AFDMemTable); //:实参克隆形参的数据和游标
//TMonitor.Exit(AFDMemTable);
except
//on E: TDSRestProtocolException do ClientModule1.HandleRestException(ClientModule1.DSRestConnection1, '客户端连接错误', E); else raise ;
raise Exception.Create('客户端连接错误');
end;
finally
if (AFDMemTable.Active=true)
then Result:=true else Result:=false;
AFDMemTable.Active:=false; //:形参,施放前线关闭
FreeAndNil(AFDMemTable); //:形参,产生和释放很重要
end;
end;
2、任务方式执行:内存表传参给公共单元获取数据
procedure TfmxMatter.btnListViewMain_SelectClick(Sender: TObject);
var ATask:ITask; AEvent:TEvent;
ADataSet: TDataSet;
begin
FDMemTMain_Temp.FetchOptions.Mode:=fmAll;
FDMemTMain_Temp.FetchOptions.RecordCountMode:=cmFetched;
FDMemTMain_Temp.FetchOptions.RowsetSize:=9999999;
FDMemTMain_Temp.FetchOptions.RecsMax:=-1;
FDMemTMain_Temp.FetchOptions.RecsSkip:=-1;
if FDMemTMain_Temp.State<>dsInactive then
begin
FDMemTMain_Temp.Close;//FDMemTMain_Temp.Active:=false;
end;
btnListViewMain_EditSelected.Enabled:=false; //:按钮执行任务前加锁很重要
Memo1.Lines.Clear;
//多任务处理预留: if arrayTasks[0].Status=TTaskStatus.Running then arrayTasks[0].Wait(INFINITE);
//ifFinishTask:=0;
AEvent:=TEvent.Create; //:创建事件总线对象
//创建并启动(多线程池化的)任务多核多处理器并行(多路CPU或GPU同时工作,或单处理器多核同步) //APool:= TThreadPool.Create; //:任务POSIX不能带池化参数产生
ATask:=TTask.Create(
procedure
var AtestFieldDefsCircle:Integer;
begin
TMonitor.Enter(self,0); //多核多处理器环境,经常用uses system; //:锁定监视器任务执行前进入锁监视状态:很重要
try
try
try // 调用上述公共单元,获取服务器返回的TDataSet数据 :
getFDMemT_SrvMethGetTFDDataSet(
'select com_id,item_id,item_name,item_type, '
+' convert(Datetime,convert(varchar(23),maintenance_datetime,121)) as maintenance_datetime '
+' from ctl03001','物品资料',FDMemTMain_Temp);
//while FDMemTMain_Temp.State=dsInactive do sleep(0);
finally
if FDMemTMain_Temp.Active=true then FDMemTMain_Temp.First;
//Memo1.Lines.Add('TFDMemTable字段数:'+IntToStr(FDMemTMain_Temp.FieldDefs.Count));
FDMemTMain_Temp.Open;
//Memo1.Lines.Add('TFDMemTable记录数:'+IntToStr(FDMemTMain_Temp.RecordCount));
FDMemTMain_Temp.Last; FDMemTMain_Temp.First;//不像其基类TDataSet,TClientDataSet可以任意操纵Cursor,而且是双向的游标。
FDMemTMain_Temp.IndexesActive:=true;
while not (FDMemTMain_Temp.Eof) do
begin
//此段代码只用于调试,POSIX不允许重复操作
//:Doublication not Allowed:
Memo1.Lines.Add(
'索引字段数:'+IntToStr(FDMemTMain_Temp.IndexFieldCount)+','
+'内存表索引记录数:'+IntToStr(FDMemTMain_Temp.IndexDefs.DataSet.RecordCount)+','
+'内存表索引:'+IntToStr(FDMemTMain_Temp.IndexDefs.DataSet.RecNo-1)+','
+'运营商编码:'+FDMemTMain_Temp.FieldByName('com_id').AsString.Trim+','
+'物品编码:'+FDMemTMain_Temp.FieldByName('item_id').AsString.Trim+','
+'物品名称:'+FDMemTMain_Temp.FieldByName('item_name').AsString.Trim+','
+'型号:'+FDMemTMain_Temp.FieldByName('item_type').AsString.Trim+','
);
FDMemTMain_Temp.Next;
end;
end;
//:上面是任务的具体内容!
AEvent.SetEvent;//:事件总线通知:任务结束!
except // 万一异常,代码很重要 :
TMonitor.Exit(self);
btnListViewMain_EditSelected.Enabled:=true;
AEvent.Free;//:出现异常释放:事件总线!
exit; //:出现异常就不要再往下执行了!
raise Exception.Create('出错或取消啦');
end;
finally
TMonitor.Exit(self); //:锁定监视器适当时机解锁:很重要
btnListViewMain_EditSelected.Enabled:=true; //:按钮适当时机解锁很重要
//AEvent.Free;
//:切忌:将事件总线在try内释放AEvent.Free;
end;
//事件总线AEvent.SetEvent后:确认任务是否完成:
//Assert(AEvent.WaitFor(15000)>TWaitResult.wrSignaled);
//:调试时:确认任务结束时长的信息标记,即AEvent.SetEvent,然后:
AEvent.Free; //:确认收到任务结束的信号标记即AEvent.SetEvent后再:释放事件总线对象
end );
//多任务管理://arrayTasks[0]:=ATask;//TTask.WaitForAll(arrayTasks); //if arrayTasks[0].Status=TTaskStatus.Running then arrayTasks[0].Wait(INFINITE);
ATask.Start;
end;
任务(多线程并行)TFDMemTable内存表传参方式调用服务器返回的TDataSet相关推荐
- 【python教程入门学习】Python函数定义及传参方式详解(4种)
这篇文章主要介绍了Python函数定义及传参方式详解(4种),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 一.函数初识 1.定 ...
- Spring Boot 传参方式
2019独角兽企业重金招聘Python工程师标准>>> 最近在搞Spring Boot的项目,把传参方式总结一下.网上也参考一些文章,总结的很不错,这里借鉴一下. 注解 @Reque ...
- axios链接带参数_axios常见传参方式
1:get请求 一般发送请求是这么写 axios.get('/user?id=12345&name=user') .then(function (res) { console.log(res) ...
- vue中路由传参方式之二(this.$router.push进行编程式路由跳转传参)
this.$router.push进行编程式路由跳转传参 router中路由配置 组件home点击传参 组件homeDetails接受参数 router中路由配置 params第一种传参路由配置 {p ...
- http请求方式及传参方式
http请求方式及传参方式 本文简单介绍一下http的几种请求方式以及集中传参方式的不同. 常见的几种请求方式 HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法. HTTP ...
- 【Postman】测试 Post 请求时传递数据失败 常见传参方式
近期尝试使用 nod.js + vue 开发一个小项目. 第一次使用 postman 测试,遇到 POST 请求数据发送不过去的问题,做一个记录. JS 部分代码 //用户注册接口 router.po ...
- Android:页面跳转传参方式一,页面跳转传参方式二
一.页面跳转传参方式一 跳转的过程如何传参:也就是页面之间如何传递参数,有点像函数调用如何传参,页面跳转也要传参. 复制一个工程 你要跳转,(现在的代码如下),intent 既然能设置跳转到哪个页面 ...
- mybatis传入数组怎么写_推荐的MyBatis传参方式List、数组等
MyBatis 推荐的传参方式 如果要详细的学习 MyBatis,推荐看这个教程:https://www.w3cschool.cn/mybatis/ 1. 单个参数//接口方法int getAgeBy ...
- Python函数传参方式超级大汇总
位置参数 位置参数传递是最为简单的传递方式,按照函数参数的位置顺序逐个匹配传入,传入参数的个数必须与函数参数个数一致. 见示例1,根据位置顺序进行匹配,a,b,c分别赋值为2,3,4 示例1 def ...
最新文章
- struts解决form提交的中文参数乱码问题
- 只导表前10条数据_【205期】面试官:数据量很大的情况下,对于分页查询你有什么优化方案吗?...
- 《2017中国大数据及AI人才发展报告》均薪38万,招聘猛增6倍
- fx5u mc协议_SLMP协议和MC协议
- 使用预先训练的SSD模型检测害虫
- Arduino编译bootloader
- 浅谈Borg/YARN/Mesos/Torca/Corona一类系统
- Java项目-食堂菜品点评系统(SpringBoot + SpringSecurity + Thymeleaf + Redis)
- UNIX 网络编程课程目录
- 园区内智慧出行标准化白皮书(2022年)
- 关于流程图的场景提炼,这一次终于说清楚业务流程图、功能流程图、页面流程图了
- 扇形涂色问题(Python)
- 上顿号符号_顿号在键盘上怎么打 常见的电脑符号输入方法说明
- 电子元器件简介——芯片封装篇
- Knockout JS 示例
- 代理对推广网站的四个作用
- C#字母与ASCII码的转换
- 10款不可多得的精美png图标
- 【UnityIUnity精灵Unity物体】生成控制大量物体的时间考究
- 跟牛老师一起学WEBGIS——WEBGIS实现(绘制切片)
热门文章
- 如何使用新版万能地图下载器下载谷歌地球影像
- linux命令进u 盘,UNetbootin Linux操作系统装进移动硬盘
- Springboot毕业设计毕设作品,图像AI风格转换系统 开题报告
- C#将服务器端excel文件下载到客户端的简单方法
- 网络编程(26)—— TIME_WAIT、FIN_WAIT1、FIN_WAIT2和CLOSE_WAIT状态的区别
- linux 更新字体
- Python+Vue计算机毕业设计电信营销派单系统4qv14(源码+程序+LW+部署)
- 美团动态线程池开源框架 DynamicTp
- python速成班1个月_Python速成班-基础篇DAY03
- 千万条记录,怎么做分页?怎么能提高性能?