繁体   English   中英

在 Delphi 中,TDataSet 线程安全吗?

[英]In Delphi, is TDataSet thread safe?

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

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

我正在 Delphi 7 中进行 Win32 编程,使用来自DAC for MySQL 的TmySQLQuery 作为我的 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 线程之外,无法以同步方式打开那些相同的 Asta 组件。

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

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

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

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

我已经做过多线程数据访问,它并不简单:

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

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

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

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

……而且异常处理也不是那么简单……

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM