Является ли TDataSet потокобезопасным в Delphi?

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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
0
4 566
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Я видел это в других реализациях 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

Из FAQ по OmniThreadLibrary (ссылка в комментарии выше) я заметил, что он поддерживает только Delphi 2007 и 2009. Кто-нибудь использовал его на D7?

Liron Yahdav 20.09.2008 01:57

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

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

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

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

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

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

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

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

Другие вопросы по теме