В Delphi поток TDataSet безопасен? - PullRequest
12 голосов
/ 17 сентября 2008

Я бы хотел иметь возможность асинхронно открывать TDataSet в своем собственном потоке, чтобы основной поток VCL мог продолжать работу до тех пор, пока это не будет сделано, а затем впоследствии прочитать основной поток VCL из этого TDataSet. Я провел некоторые эксперименты и попал в очень странные ситуации, поэтому мне интересно, делал ли это кто-то раньше.

Я видел несколько примеров приложений, в которых TDataSet создается в отдельном потоке, открывается и затем из него считываются данные, но все это делается в отдельном потоке. Мне интересно, безопасно ли читать из TDataSet из основного потока VCL после того, как другой поток открывает источник данных.

Я занимаюсь программированием на Win32 в Delphi 7, используя TmySQLQuery из DAC для MySQL в качестве моего потомка TDataSet.

Ответы [ 6 ]

5 голосов
/ 17 сентября 2008

Если вы хотите использовать только набор данных в своем собственном потоке, вы можете просто использовать синхронизацию для связи с основным потоком для любого обновления VCL / UI, как и с любым другим компонентом.
Или, что еще лучше, вы можете реализовать связь между mainthread и рабочими потоками с вашей собственной системой обмена сообщениями.

проверьте решение 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

3 голосов
/ 17 сентября 2008

При использовании одного и того же TDataSet между несколькими потоками следует помнить, что в любой момент времени вы можете только читать текущую запись. Так что, если вы читаете запись в одном потоке, а затем другой поток вызывает Next , то у вас проблемы.

3 голосов
/ 17 сентября 2008

Я видел, как это было сделано с другими реализациями TDataSet, а именно с Asta компонентами. Они будут связываться с сервером, немедленно возвращаться и затем запускать событие после загрузки данных.

Однако я считаю, что это очень сильно зависит от компонента. Например, те же компоненты Asta не могут быть открыты синхронно из чего-либо, кроме основного потока VCL.

Короче говоря, я не считаю, что это ограничение TDataSet само по себе, а скорее что-то, зависящее от реализации, и у меня нет доступа к компонентам, которые вы упомянули.

2 голосов
/ 17 сентября 2008

Также помните, что потоку, скорее всего, потребуется собственное соединение с базой данных. Я считаю, что здесь необходим многопоточный «удерживающий» объект для загрузки данных из потока в (только запись), который затем читается только из основного потока VCL. Перед чтением используйте какой-либо метод синхронизации, чтобы убедиться, что вы не читаете в тот же момент, когда пишете, или пишете в тот же момент, когда читаете, или загружаете все в файл памяти и пишете метод синхронизации, чтобы сообщить основному приложению, где в файле прекратить чтение.

Я несколько раз использовал последний подход, в зависимости от количества ожидаемых записей (и размера набора данных), я даже перенес это в файл физического диска в локальной системе. Работает довольно хорошо.

1 голос
/ 17 сентября 2008

Я сделал многопоточный доступ к данным, и это не так просто:

1) Вам необходимо создать сеанс для каждого потока.

2) Все, что сделано с этим экземпляром TDataSet, должно быть сделано в контексте потока, в котором он был создан. Это не легко, если вы хотите разместить, например, Сетка ДБ поверх него.

3) Если вы хотите, например, Основной поток игры с вашими данными, простое решение состоит в том, чтобы переместить их в отдельный контейнер какого-либо типа, например. набор данных памяти.

4) Вам нужен какой-то механизм сигнализации, чтобы уведомить основной поток после завершения поиска данных.

... и обработка исключений также не проста ...

Но: как только вы добьетесь успеха, приложение будет действительно элегантным!

0 голосов
/ 20 сентября 2008

Большинство TDatasets не являются потокобезопасными. Я знаю, что потокобезопасный - это kbmMemtable . Он также имеет возможность клонировать набор данных, так что возникает проблема перемещения указателя записи (как объяснил Джим Маккит). Это один из лучших наборов данных, которые вы можете получить (купленные или бесплатные).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...