倾囊而出!!一个多线程中操作数据库的问题,急!!在线等候!! (200分)

  • 主题发起人 主题发起人 leo_cdp
  • 开始时间 开始时间
L

leo_cdp

Unregistered / Unconfirmed
GUEST, unregistred user!
想请教一个关于多线程问题!
我现在做一个定时执行存储过程(oracle用BDE方式连接),以多线程实现,主要有以下模块。
一。作业队列生成.以定时器,定时查询数据库且与当前时间匹配,添加到任务队列:TASKLIST中
二。作业启动线程,完成以下功能:判断当前执行队列(TaskInRun)中是否有此作业在运行,有则进入堵塞队列中。
没有则生成“执行线程”执行作业,见三。
三。作业执行线程:请求数据库资源,依据传入的作业ID取得作业参数及数据连接等待资料。生成执行单元(factory method)
唤醒进程后,运行执行单元。执行完成后删除TaskInRun中的本作业的记录,再查询堵塞队列中是否有本作业有则加入执行队列中
以上是主要的框架,测试在作业数小的话运行正常。但是当作业数多的话则出现:insufficient memory to do this operation类似的错误。
我想问题是出在线程中数据库连接资源的使用上,我对于在多线程中使用数据不大明白,只知道要在独立的session中进行操作,但是这样
我要为每个作业分配两个数据库连接(一个用于取得参数别一个用于执行作业[作业可能与配置表不在同一数据库])这样资源要求很大,一般
只能同时执行十几个线程。请问有什么好的解决方法?
附执行线程的代码。
constructor TExecTask.create(Prg_id: integer;prg_type: string);
begin
inherited create(true);
program_id := prg_id;
Program_type := prg_type;

//本线程内使用的数据库的初始化。
DatabaseL := TDatabase.Create(nil);
SessionL := TSession.Create(nil);
Qry_Local := TQuery.Create(nil);
SessionL.SessionName := 'Sessp'+inttostr(getnum);
with DatabaseL do
begin
SessionName := SessionL.SessionName;
DatabaseName := 'D'+SessionL.SessionName;
AliasName := 'dhgl';
Params.Values['USER NAME'] := 'test';
Params.Values['password'] := 'testabc';
LoginPrompt := false;
end;
Qry_Local.SessionName := SessionL.SessionName;
Qry_Local.DatabaseName := DatabaseL.DatabaseName;

//初始化执行单元。此中有一个数据库资源。有独立的session和TDatabase
Factory := CreateFactory(prg_type,DatabaseL.DatabaseName,SessionL.SessionName);
Eu := factory.newInstances(prg_id);

//日志初始化。
LogIt := SysLog.Create;
LogIt.SetQryPre(DatabaseL.DatabaseName,SessionL.SessionName);
LogId := LogIt.Start(Prg_Id);

//填写系统正在执行的任务队列。
TaskInRun.add(inttostr(prg_id),prg_type);
//唤醒线程。
resume;
end;

procedure TExecTask.Execute;
var succ:boolean;
begin
{ Place thread code here }
//执行作业
try
EU.Execute;
LogIt.done(LogId,'done','succ');
succ := true;
except
LogIt.done(LogId,'done','Fail');
succ := false;
//添加灾难恢复的处理作业。
//..........todo:
end;

//查询是否有依赖于此作业的其它作业;
if succ then //成功则执行。
with Qry_local do
begin
try
close;
sql.clear;
sql.add('select prg_id,prg_type from t_timeprg where PARENT_ID='+inttostr(program_id));
open;
while not eof do
begin
TaskList.add(fieldbyname('PRG_ID').asstring,fieldbyname('PRG_TYPE').asstring);
next;
end;
except
LogIt.Done(LogId,'完成','生成赖于此作业的其它作业队列失败!');
end;
end;

//完成任务后删除其在正在运行的任务队列中的记录 。
TaskInRun.delete(TaskInRun.IndexOf(inttostr(program_id)));

//唤醒等待的作业。注意:必须在上一操作执行完成后进行。
if TaskWaitRun.IndexOf(inttostr(program_id)) <> -1 then
begin
TaskList.add(inttostr(program_id),Program_type);
TaskWaitRun.delete(TaskWaitRun.IndexOf(inttostr(program_id)));
end;
//完成本线程的所有任务释放资源。
eu.Destory;
Qry_local.Close;
DatabaseL.Connected := false;
Qry_local.Destroy;
DatabaseL.Destroy;
SessionL.Destroy;
end;
 
你的线程有没有释放???
你连接数据库可以共用一个Session啊
 
insufficient memory to do this operation

我怀疑是BDE本身的问题,试试用ADO可以吗?
 
我们系统规定只能用BDE不能用ADO
共享Session是什么意思,那样好像会出错我做了简单的同步后,它报错说违后读取顺序!
 
Session确实对内存要求很大,如果用多线程,就要用多个Session,
用ADO可以,可惜你又用Oracle,只好同步线程了
或者建一个线程专门操作数据库,其他线程发出申请。
 
多人接受答案了。
 
后退
顶部