14

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

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

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

4

6 回答 6

5

如果您只想在自己的线程中使用数据集,您可以使用同步与主线程进行任何 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

于 2008-09-17T08:28:46.607 回答
4

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

但是,我相信这在很大程度上取决于组件。例如,除了主 VCL 线程之外,无法以同步方式打开这些相同的 Asta 组件。

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

于 2008-09-17T00:10:23.793 回答
3

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

于 2008-09-17T01:22:56.040 回答
2

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

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

于 2008-09-17T03:00:07.240 回答
1

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

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

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

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

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

...而且异常处理也不是直截了当的...

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

于 2008-09-17T11:00:10.673 回答
0

大多数 TDatasets 不是线程安全的。我知道线程安全的是kbmMemtable。它还具有克隆数据集的能力,因此确实会出现移动记录指针的问题(如 Jim McKeeth 所解释的)。它们是您可以获得(购买或免费)的最佳数据集之一。

于 2008-09-20T03:28:14.627 回答