首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何正确访问在后台线程中创建的查询结果?

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

Stack Overflow用户
提问于 2010-02-21 10:19:08
回答 2查看 973关注 0票数 7

我想在后台线程中执行数据库查询。OmniThread库将帮助我处理所有的线程内容,但有一件事我至今还不明白:

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

现在,我可以使用后台线程的query对象访问查询结果。

但是在执行查询之后,我希望访问主线程中的查询结果。

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

据我所知,在这种情况下,主线程不会有单独的DB连接,并且使用与后台线程不太好的连接。

我的思维哪里扭曲了,怎么做才是正确的呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-02-21 12:09:25

如果您的OTL任务需要加载符合条件的公司排序列表:

代码语言:javascript
复制
// 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线程:

代码语言:javascript
复制
Task.Comm.Send(TOmniMessage.Create(MSGID_LIST_OF_COMPANIES, Companies));

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

代码语言:javascript
复制
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位整数,一个时间戳也可以工作),这个索引随每次更新而改变。而不是执行

从foo (.)中选择*(.)命令

我只执行过

从foo选择id,change_index (.)(.)命令

然后在缓存中签入具有相同id (主键)和更改索引的对象是否已经存在,如果存在,则返回缓存对象,并且只有在不创建新的业务对象并加载所有列的情况下。

但是,如果您缓存对象,您将从多个线程获得对它们的引用,并且所有权问题很快变得非常复杂,因此基于引用计数的生命周期管理是保持正常状态的唯一方法。在这个regard.

  • Adding中,使用接口而不是对象非常有帮助--如果多个线程可以同时访问它们,则每个业务对象的同步对象是必要的。当然,这是可能的,但可能会带来额外的复杂性和潜在的死锁。如果您将业务对象实现为不可变,那么根本不需要锁。我越来越多地使用这种方法,虽然需要一些时间才能适应它,但它可以简化很多事情。
票数 12
EN

Stack Overflow用户

发布于 2010-02-21 10:47:41

最好的方法可能是在GUI中不使用可识别数据库的组件。线程应该与数据库通信,并将信息存储在业务对象中,然后将这些信息发送到主线程(后者将显示它们)。

多线程是困难的,不仅从实现的角度,而且从应用程序设计的角度来看。通常情况下,最好将后台线程看作一个单独的层,具有定义良好的输入和输出。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2305560

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档