我希望能够在自己的线程中异步打开 TDataSet,以便主 VCL 线程可以继续执行直到完成,然后让主 VCL 线程从该 TDataSet 中读取数据。我做了一些实验,遇到了一些非常奇怪的情况,所以我想知道以前是否有人这样做过。

我见过一些示例应用程序,其中 TDataSet 在单独的线程中创建,打开它,然后从中读取数据,但这都是在单独的线程中完成的。我想知道在另一个线程打开数据源后,从主 VCL 线程读取 TDataSet 是否安全。

我正在 Delphi 7 中使用 TmySQLQuery 进行 Win32 编程 MySQL 的 DAC 作为我的 TDataSet 后代。

有帮助吗?

解决方案

如果您只想在自己的线程中使用数据集,则可以使用同步与主线程进行任何 VCL/UI 更新的通信,就像与任何其他组件一样。
或者,更好的是,您可以使用自己的消息系统实现主线程和工作线程之间的通信。

在这里检查 Hallvard 的线程解决方案:
http://hallvards.blogspot.com/2008/03/tdm6-knitting-your-own-threads.html

或另一个:
http://dn.codegear.com/article/22411

有关同步及其低效率的一些解释:
http://www.eonclash.com/Tutorials/Multithreading/MartinHarvey1.1/Ch3.html

其他提示

我已经看到它与 TDataSet 的其他实现一起完成,即在 阿斯塔 成分。这些将联系服务器,立即返回,然后在数据加载后触发一个事件。

然而,我相信这在很大程度上取决于组件。例如,这些相同的 Asta 组件无法从主 VCL 线程以外的任何其他地方以同步方式打开。

简而言之,我不认为这是 TDataSet 本身的限制,而是特定于实现的限制,并且我无权访问您提到的组件。

使用相同的东西要记住一件事 数据集 在多个线程之间,您只能在任何给定时间读取当前记录。因此,如果您正在一个线程中读取记录,然后另一个线程调用 下一个 那么你就有麻烦了。

另请记住,线程很可能需要自己的数据库连接。我相信这里需要的是一个多线程“持有”对象,用于将数据从线程加载到(只写)中,然后从主 VCL 线程中只读。在阅读之前,使用某种同步方法来确保您不会在阅读的同一时刻阅读,或者在阅读的同一时刻写入,或者将所有内容加载到内存文件中并编写一个同步方法来告诉主应用程序在文件中的位置停止阅读。

我已经多次采用最后一种方法,具体取决于预期记录的数量(以及数据集的大小),我什至将其保存到本地系统上的物理磁盘文件中。它运作得很好。

我已经完成了多线程数据访问,但并不简单:

1)您需要为每个线程创建一个会话。

2)对该TDataSet实例所做的一切都必须在创建它的线程的上下文中完成。如果你想放置例如,这并不容易。其顶部有一个数据库网格。

3)如果你想让例如主线程处理您的数据,直接的解决方案是将其移动到某种单独的容器中,例如内存数据集。

4)一旦数据检索完成,您需要某种信号机制来通知主线程。

...异常处理也并不简单...

但:一旦你成功了,应用程序将变得非常优雅!

大多数 TDataset 都不是线程安全的。我知道线程安全的一个是 KBM内存表. 。它还具有克隆数据集的能力,因此确实会发生移动记录指针的问题(如 Jim McKeeth 所解释)。它们是您可以获得的最好的数据集之一(购买或免费)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top