Hol*_*rwa 7 database delphi multithreading delphi-2009
我想在后台线程中执行数据库查询.OmniThread库将帮助我完成所有的线程,但到目前为止我还有一件事情我不明白:
每个线程都需要单独的数据库连接.后台线程因此创建数据库连接,创建查询然后执行它.
现在我可以使用后台线程的查询对象访问查询结果.
但是在执行查询之后,我想在主线程中访问查询结果.
如果我只是引用后台线程查询对象,这是否会导致问题,因为我正在访问另一个线程中的数据库连接?
据我所知,在这种情况下,主线程不会有它独立的数据库连接,并使用后台线程中的那个并不好.
我的想法在哪里被扭曲,这是做正确的方法?
mgh*_*hie 12
如果您的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;
Run Code Online (Sandbox Code Playgroud)
C是您公司的业务对象.它可以由object(TCompany)或ICompany对象实现的接口()实现.Companies是一个TList<TCompany>或TList<ICompany>.在任务结束时,您将公司列表发送到VCL线程:
Task.Comm.Send(TOmniMessage.Create(MSGID_LIST_OF_COMPANIES, Companies));
Run Code Online (Sandbox Code Playgroud)
在您要显示公司列表的表单中,您处理监视任务OnTaskMessage的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;
Run Code Online (Sandbox Code Playgroud)
公司列表取代了以前的列表,可以在网格中显示.
同样,您可以返回单个公司对象/界面进行显示和编辑.
值得思考的两件事:
如果你到目前为止已经有了接口的首选对象,那么编写多线程程序可能是重新考虑它的一个原因.如果您在后台线程中创建对象,然后将它们传递给VCL线程并在后台线程中忘记它们,那么对象可能会正常工作.然而,我发现通过在应用程序中缓存对象,并且只加载尚未加载或已更改的数据库中的记录,可以获得更好的性能.我的所有表都附加了一个更改索引(64位整数,时间戳也可以工作),每次更新都会更改.而不是执行
select * from foo where (...) order by (...)
Run Code Online (Sandbox Code Playgroud)
我只执行过一次
select id, change_index from foo where (...) order by (...)
Run Code Online (Sandbox Code Playgroud)
然后在高速缓存中检查具有相同id(主键)和更改索引的对象是否已存在,如果是,则返回高速缓存对象,并且仅在不创建新业务对象并加载所有列时.
但是如果你缓存对象,你将从多个线程中引用它们,并且所有权问题很快变得如此复杂,以至于基于引用计数的生命周期管理是保持理智的唯一方法.在这方面使用接口而不是对象有很大帮助.
如果多个线程可以同时访问它们,则必须向每个业务对象添加同步对象.这当然是可能的,但可能会引入额外的复杂性和潜在的死锁.如果将业务对象实现为不可变,则根本不需要锁.我越来越多地使用这种方法,虽然它需要一些习惯,但它可以简化很多事情.
最好的方法可能是不在GUI中使用db-aware组件.线程应该与数据库通信并将信息存储在业务对象中,然后可以将其发送到主线程(将显示它们).
多线程很难,不仅从实现的角度来看,而且从应用程序设计的角度来看也是如此.通常最好将背景线程视为具有明确定义的输入和输出的单独层.