Я хотел бы иметь возможность асинхронно открывать TDataSet в своем собственном потоке, чтобы основной поток VCL мог продолжать работу до тех пор, пока это не будет сделано, а затем после этого основной поток VCL считывался из этого TDataSet. Я экспериментировал и попадал в очень странные ситуации, поэтому мне интересно, делал ли кто-нибудь это раньше.
Я видел несколько примеров приложений, в которых TDataSet создается в отдельном потоке, он открывается, а затем из него считываются данные, но все это делается в отдельном потоке. Мне интересно, безопасно ли читать из TDataSet из основного потока VCL после того, как другой поток откроет источник данных.
Я занимаюсь программированием Win32 в Delphi 7, используя TmySQLQuery из DAC для MySQL в качестве моего потомка TDataSet.





Я видел это в других реализациях TDataSet, а именно в компонентах Аста. Они связывались с сервером, немедленно возвращались, а затем запускали событие после загрузки данных.
Однако я считаю, что это очень сильно зависит от компонента. Например, те же самые компоненты Asta нельзя было открыть синхронно из чего-либо, кроме основного потока VCL.
Короче говоря, я не считаю, что это ограничение TDataSet как таковое, а скорее то, что зависит от реализации, и у меня нет доступа к компонентам, о которых вы упомянули.
При использовании одного и того же TDataSet между несколькими потоками следует иметь в виду, что вы можете читать только текущую запись в любой момент времени. Итак, если вы читаете запись в одном потоке, а затем другой поток вызывает Следующий, у вас проблемы.
Также помните, что потоку, скорее всего, потребуется собственное соединение с базой данных. Я считаю, что здесь нужен многопоточный «удерживающий» объект для загрузки данных из потока (только для записи), который затем читается только из основного потока VCL. Перед чтением используйте какой-то метод синхронизации, чтобы убедиться, что вы не читаете в тот же момент, когда пишете, или пишете в тот же момент, когда читаете, или загружаете все в файл памяти и напишите метод синхронизации, чтобы сообщить главному приложению, где в файле нужно перестань читать.
Я использовал последний подход несколько раз, в зависимости от количества ожидаемых записей (и размера набора данных). Я даже перенес его в файл физического диска в локальной системе. Работает неплохо.
Если вы хотите использовать набор данных только в его собственном потоке, вы можете просто использовать синхронизацию для связи с основным потоком для любого обновления 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
Я сделал многопоточный доступ к данным, и это непросто:
1) Вам нужно создать сеанс для каждого потока.
2) Все, что делается с этим экземпляром TDataSet, должно выполняться в контексте потока, в котором он был создан. Это непросто, если вы хотите разместить, например, поверх него сетка db.
3) Если вы хотите, например, основной поток играет с вашими данными, простое решение - переместить его в отдельный контейнер какого-либо типа, например. Набор данных памяти.
4) Вам нужен какой-то механизм сигнализации, чтобы уведомить основной поток после завершения извлечения данных.
... и обработка исключений тоже не проста ...
Но: Как только вы добьетесь успеха, приложение станет действительно элегантным!
Большинство наборов данных TD не являются потокобезопасными. Я знаю, что потокобезопасным является kbmMemtable. Он также имеет возможность клонировать набор данных, чтобы проблема с перемещением указателя записи (как объяснил Джим МакКит) действительно возникала. Это одни из лучших наборов данных, которые вы можете получить (купленные или бесплатные).
Из FAQ по OmniThreadLibrary (ссылка в комментарии выше) я заметил, что он поддерживает только Delphi 2007 и 2009. Кто-нибудь использовал его на D7?