Multithreading 在Delphi中,TDataSet是线程安全的吗?

Multithreading 在Delphi中,TDataSet是线程安全的吗?,multithreading,delphi,dataset,Multithreading,Delphi,Dataset,我希望能够在自己的线程中异步打开TDataSet,以便主VCL线程可以继续,直到完成为止,然后从该TDataSet读取主VCL线程。我做了一些实验,遇到了一些非常奇怪的情况,所以我想知道以前是否有人这样做过 我见过一些示例应用程序,其中TDataSet是在单独的线程中创建的,它被打开,然后从中读取数据,但这些都是在单独的线程中完成的。我想知道在另一个线程打开数据源后,从主VCL线程读取TDataSet是否安全 我正在Delphi 7中进行Win32编程,使用TmySQLQuery from作为我

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

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


我正在Delphi 7中进行Win32编程,使用TmySQLQuery from作为我的TDataSet子代。

我看到它是通过TDataSet的其他实现完成的,即在组件中。它们将联系服务器,立即返回,然后在加载数据后触发事件

不过,我相信这在很大程度上取决于组成部分。例如,那些相同的Asta组件不能从主VCL线程以外的任何线程以同步方式打开


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

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

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


我曾多次采用最后一种方法,根据预期记录的数量(以及数据集的大小),我甚至将其带到本地系统上的物理磁盘文件中。它工作得很好。

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

在此处查看Hallvard的线程解决方案:

或者另一个:

有关同步及其低效性的一些解释:

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

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

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

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

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

…而且异常处理也不简单


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

大多数TDataset都不是线程安全的。一个我知道是线程安全的是。它还能够克隆一个数据集,这样就不会出现移动记录指针的问题(如Jim McKeeth所解释的)。它们是您可以获得的最好的数据集之一(购买或免费)。

我从OmniThreadLibrary的常见问题解答(上面评论中的链接)中注意到,它只支持Delphi 2007和2009。有人在D7上用过吗?