【问题标题】:TOraDataSet blocking my program even with NonBlocking set to true即使将 NonBlocking 设置为 true,TOraDataSet 也会阻止我的程序
【发布时间】:2017-11-01 05:03:14
【问题描述】:

我试图做一个小闪屏,这样我的程序就可以打开查询而不会阻止我的应用程序。 我写的代码是这样的。

procedure TOpenThread.OpenTable;
begin
  FActiveTable.NonBlocking := true;
  FActiveTable.open;
end;
procedure TOpenThread.AbrirTablas;
begin
    FActiveTable := FOwnerPlan.TablasEdicion.Tabla;
    Synchronize(OpenTable);
    while FActiveTable.Executing do
    begin
     if Terminated then CancelExecution;
     sleep(10);
    end;
    FActiveTable.NonBlocking := false;
end;

这段代码在一个线程中执行,并且在主线程卡住时继续执行

我用的是delphi 2007

【问题讨论】:

  • 主线程阻塞在哪里?

标签: oracle delphi delphi-2007 odac


【解决方案1】:

这段代码在线程中执行

现在,它没有。你的代码是:

Synchronize(OpenTable);

这明确表示 OpenTable 过程在主 VCL 线程内和后台辅助 TOpenThread 之外执行。

有关Synchronize 的更多详细信息,您可以尝试从https://stackoverflow.com/a/44162039/976391 中学习

总而言之,复杂的问题没有简单的解决方案。

如果您想将数据库交互卸载到单独的线程中,则必须使该线程独占所有数据库组件的所有者和用户,从数据库连接开始,一直到每个事务和每个查询。

然后你必须设法从主 VCL 线程异步发布数据请求到 DB 辅助线程,并异步接收来自它的数据包。 像 OmniThreadLibrary 一样处理数据流 - 阅读他们的教程以了解使用多线程时的内部程序结构。

您可以尝试将您的应用程序修改为以下经验法则。 它不会是最快的多线程,但可能是最简单的。

  • 所有数据库组件的工作都是在TOpenThread.Execute 上下文中专门完成的,这些组件是TOpenThread 类的局部成员变量。仅在TOpenThread.Execute内进行的连接断开; TOpenThread.Execute 在几乎无限(直到线程终止)和节流循环中等待来自主线程的命令。

  • 特定的数据库请求以anonymous procedures 的形式发出,并添加到TOpenThread 对象的一些TThreadedQueue<T> 公共成员中。 .Execute 内部的循环尝试从该队列中获取操作并执行它(如果存在),或者如果队列为空则限制 (Yield())。数据库操作周围不允许使用 Synchronize 和 Queue 包装器。 VCL 主线程只发布请求,但从不等待它们实际执行。

  • 那些匿名程序在执行后确实会将数据库结果传回主线程。喜欢http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/ 或喜欢Sending data from TThread to main VCL Thread 或任何其他返回主线程的方式。

  • TOpenThread.Execute 仅在设置了 Terminated 标志且队列为空时退出循环。如果设置了Terminated,那么立即退出将丢失仍在等待未处理队列的操作。

看起来枯燥乏味但很容易?一点也不,补充一下,你必须拦截异常并以异步方式处理所有错误——你会“失去任何进入这个领域的希望”。

PS。最后但并非最不重要的一点是,关于“这段代码在一个线程中执行,并且在主线程被卡住时继续执行”假设,坦率地说,我想你在这里错了,我认为你的两个线程都被卡住了. 如果不完全了解线程到线程锁定是如何设计用于这个特定组件的,通过调用Synchronize 和其他线程间锁定工具来地毯式轰炸代码,您很有机会将所有线程都追逐到互锁、死锁的状态。见http://stackoverflow.com/questions/34512/

【讨论】:

  • 是的,但是数据集的“NonBlocking”属性应该让它在主线程之外执行
  • 不,方法OpenTable在主线程中执行。如果没有——那么就没有理由去创建TOpenThread——只需从你的主线程代码中调用.OpenTable!问题是某些活动(但不是全部!)不再在OpenTable 内执行,而是被卸载以由其他一些方法执行。我不确定。然而,绝对正确的是,Synchronize 正在为其参数杀死多线程,这就是引入该调用的目的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-16
  • 2013-08-19
  • 2023-03-17
  • 2015-03-04
  • 2017-10-25
  • 1970-01-01
相关资源
最近更新 更多