【发布时间】:2012-10-11 04:01:16
【问题描述】:
使用 Indy 10 TCP 命令处理程序,每次收到命令时,我都会在数据库中插入一行,然后从数据库中读取整个故事以更新字符串网格。
我正在使用 AnyDac 数据库组件,他们的文档说“一个连接对象和所有与之关联的对象(如 TADQuery、TADTransaction 等)在每个时刻都必须由单个线程使用”。
如果我“缓慢”发送 TCP 命令,则没有问题。如果我“快速”发送它们(当 AnyDac 仍在显示 SQL 光标时,我会收到异常 EDatabaseError "field not found" - 但它当然存在。
当我收到 TCP 命令时,我的代码使用 PostMEssage 将 UM_ 发送到我的主窗体。
我认为正在发生的事情是,由于第一个 TCP 命令,主要形式是从表中读取所有行,而 TCP 命令处理程序在插入新行的过程中途作为第二个命令的结果 - 因此当我调用 ADQuery1.FieldByName() 时“找不到字段”。
这听起来像问题吗?
如果是这样,我该如何预防?可以使用关键部分(在哪里,主线程?)?还是有其他方法?
[更新] 我刚刚意识到 - 这不可能是线程问题(我认为)。当我收到一个 TCP 命令时,我使用 PostMessage() 将一个 UM_ 发送到我的主窗体。因此,无论 TCP 命令来得有多快,我的主窗体一次只能通过其消息队列处理一个 UM_。 TCP 命令处理程序只需一行即可发送该消息 - 没有 d/b 访问权限。
但是-我不明白的是,如果在 TCP 命令之间留出“一段时间”一切都很好,但是如果我“快速”发送它们,那么我会收到异常说在那一行中没有这样的字段桌子。
[更新] 事实上,我终于解决了这个问题,问题是使用了更新速度相当慢的 TStringGrid。有一些方法可以让它更快,但我决定将它转换为 TDbGrid,它的更新速度非常快。
【问题讨论】:
-
在同时访问数据库的每个线程中,您应该使用专用的 TADConnection,或者您应该序列化从多个线程对 TADConnection 和相关对象的访问。首先是更简单和推荐。更多信息:da-soft.com/anydac/docu/Multi_Threading.html
-
+1 但是,请查看我的更新。我不认为这可能是线程问题。我认为我这样想是错误的。
-
“字段未找到”可能有多种原因: 1)数据集已关闭。 2) 为没有该字段的 SELECT 打开了一个数据集,然后在另一个期望该字段存在的上下文中使用。 3) 对数据集的多线程访问杀死了内部结构。 4) 只是您的代码中的一个错误,它需要该字段,但 SELECT 不返回该字段。 5) 数据库结构被即时更改,因此表中不再存在该字段。
-
+1 但是......它是 100% 一致的 - 如果我“慢慢地”这样做它总是成功,但如果我“快速”地这样做它会失败(并且快速意味着可能 0.5 到 1 秒
-
这看起来像一个同步问题。
标签: delphi thread-safety critical-section indy10