database – 如何正确访问后台线程中创建的查询结果?

前端之家收集整理的这篇文章主要介绍了database – 如何正确访问后台线程中创建的查询结果?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想在后台线程中执行数据库查询. OmniThread库将帮助我完成所有的线程,但到目前为止我还有一件事情我不明白:

每个线程都需要单独的数据库连接.后台线程因此创建数据库连接,创建查询后执行它.

现在我可以使用后台线程的查询对象访问查询结果.
但是在执行查询之后,我想在主线程中访问查询结果.

如果我只是引用后台线程查询对象,这是否会导致问题,因为我正在访问另一个线程中的数据库连接?

据我所知,在这种情况下,主线程不会有它独立的数据库连接,并使用后台线程中的那个并不好.

我的想法在哪里被扭曲,这是做正确的方法

解决方法

如果您的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)实现.公司是TList< TCompany>或TList< ICompany>.在任务结束时,您将公司列表发送到VCL线程:

Task.Comm.Send(TOmniMessage.Create(MSGID_LIST_OF_COMPANIES,Companies));

在您要显示公司列表的表单中,您处理正在监视任务的otlEventMonitor实例的OnTaskMessage事件:

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;

公司列表取代了以前的列表,可以显示在网格中.

同样,您可以返回单个公司对象/界面进行显示和编辑.

值得思考的两件事:

>如果到目前为止您已经有了接口的首选对象,那么编写多线程程序可能是重新考虑这一点的理由.如果您在后台线程中创建对象,然后将它们传递给VCL线程并在后台线程中忘记它们,那么对象可能会正常工作.然而,我发现通过在应用程序中缓存对象,并且只加载尚未加载或已更改的数据库中的记录,可以获得更好的性能.我的所有表都附加了一个更改索引(64位整数,时间戳也可以工作),每次更新都会更改.而不是执行

select * from foo where (...) order by (...)

我只执行过一次

select id,change_index from foo where (...) order by (...)

然后在高速缓存中检查具有相同id(主键)和更改索引的对象是否已存在,如果是,则返回高速缓存对象,并且仅在不创建新业务对象并加载所有列时.

但是如果你缓存对象,你将从多个线程中引用它们,并且所有权问题很快变得如此复杂,以至于基于引用计数的生命周期管理是保持理智的唯一方法.在这方面使用接口而不是对象有很大帮助.>如果多个线程可以同时访问它们,则必须向每个业务对象添加同步对象.这当然是可能的,但可能会引入额外的复杂性和潜在的死锁.如果将业务对象实现为不可变,则根本不需要锁.我越来越多地使用这种方法,虽然它需要一些习惯,但它可以简化很多事情.

猜你在找的Delphi相关文章