我想在后台线程中执行数据库查询。OmniThread库将帮助我处理所有的线程内容,但有一件事我至今还不明白:
每个线程都需要一个单独的数据库连接。因此,后台线程创建DB连接,创建查询,然后执行查询。
现在,我可以使用后台线程的query对象访问查询结果。
但是在执行查询之后,我希望访问主线程中的查询结果。
如果我只是引用后台线程查询对象,这是否会导致问题,因为我正在访问另一个线程中的DB连接?
据我所知,在这种情况下,主线程不会有单独的DB连接,并且使用与后台线程不太好的连接。
我的思维哪里扭曲了,怎么做才是正确的呢?
发布于 2010-02-21 12:09:25
如果您的OTL任务需要加载符合条件的公司排序列表:
// create and open query to fetch list of companies
while not qryCompanies.Eof do begin
C := TCompany.Create;
try
C.LoadFromDataset(qryCompanies);
Companies.Add(C);
except
C.Free;
raise;
end;
qryCompanies.Next;
end;C是公司的业务对象。它可以由对象(TCompany)或由对象实现的接口(ICompany)实现。Companies是TList<TCompany>或TList<ICompany>。在任务结束时,将公司列表发送到VCL线程:
Task.Comm.Send(TOmniMessage.Create(MSGID_LIST_OF_COMPANIES, Companies));在要显示公司列表的表单中,您要处理监视任务的otlEventMonitor实例的otlEventMonitor事件:
procedure TListBaseFrame.otlEventMonitorTaskMessage(
const task: IOmniTaskControl);
var
MsgID: word;
MsgValue: TOmniValue;
begin
task.Comm.Receive(MsgID, MsgValue);
Assert(MsgValue.IsInterface);
if fLoaderTask = task then begin
SetLoadedData(MsgID, MsgValue.AsInterface); // or MsgValue.AsObject);
fLoaderTask := nil;
end;
end;公司列表取代了以前的列表,可以在网格中显示。
类似地,您可以返回要显示和编辑的单个公司对象/接口。
有两件事值得考虑:
如果到目前为止,
从foo (.)中选择*(.)命令
我只执行过
从foo选择id,change_index (.)(.)命令
然后在缓存中签入具有相同id (主键)和更改索引的对象是否已经存在,如果存在,则返回缓存对象,并且只有在不创建新的业务对象并加载所有列的情况下。
但是,如果您缓存对象,您将从多个线程获得对它们的引用,并且所有权问题很快变得非常复杂,因此基于引用计数的生命周期管理是保持正常状态的唯一方法。在这个regard.
发布于 2010-02-21 10:47:41
最好的方法可能是在GUI中不使用可识别数据库的组件。线程应该与数据库通信,并将信息存储在业务对象中,然后将这些信息发送到主线程(后者将显示它们)。
多线程是困难的,不仅从实现的角度,而且从应用程序设计的角度来看。通常情况下,最好将后台线程看作一个单独的层,具有定义良好的输入和输出。
https://stackoverflow.com/questions/2305560
复制相似问题