Многопоточность запросов DbExpress

Я использовал только "GUI" доступ к базе данных в Delphi с компонентами DbExpress, но теперь я хотел бы выполнить один запрос в фоновом режиме. Я читал кое-где, что TSQLConnection не является потокобезопасным, и мне нужно создавать новое соединение для каждого потока. Я вижу, что в TSQLConnection есть CloneConnection, но справка утверждает, что новые соединения принадлежат исходному соединению.

So,

1) Как правильно выполнить TSQLQuery, расположенный на многопоточном модуле данных?

2) Могу ли я использовать TSQLConnection.CloneConnection? Должен ли я освободить клонированные соединения или оставить их нетронутыми после завершения потока?

Простой пример кода (или URL) был бы очень полезен.


person Harriv    schedule 03.02.2009    source источник


Ответы (1)


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

Что вы можете сделать, так это поместить все в TDataModule. Если модуль данных может работать сам по себе, не нуждаясь в других компонентах в других формах или модулях данных, и вы создаете его в фоновом потоке, то вы можете быть уверены, что все будет работать. Вам не нужно клонировать соединение, так как оно будет создано и уничтожено в том же потоке, где осуществляется весь доступ к базе данных.

Несколько важных советов по работе с базой данных с фоновыми потоками:

  • Обрабатывайте все исключения, так как необработанные исключения во вторичном потоке могут привести к сбою вашего приложения. Обработка исключений в объекте Application у вас не сработает.

  • Не обращайтесь ни к чему в потоке графического интерфейса. Это означает, что наиболее важно то, что TDataSource нельзя использовать, и нельзя использовать никакие элементы управления, чувствительные к данным.

  • Если используемые вами компоненты делают что-либо с SendMessage или PostMessage, вам придется создать стандартный цикл сообщений в фоновом потоке.

  • Если используемые вами компоненты что-либо делают с OLE, вызовите как OleInitialize (), так и OleUnitialize () в контексте фонового потока.

Если вы хотите облегчить себе жизнь, рассмотрите возможность использования OmniThreadLibrary или AsyncCalls. Какой из них зависит от того, как долго будут жить ваши фоновые подключения к базе данных и хотите ли вы их повторно использовать.

person mghie    schedule 03.02.2009
comment
Самая большая проблема с текущим решением заключается в том, что у меня есть несколько взаимозависимых модулей данных (соединение находится в другом модуле данных, чем запрос). Но я посмотрю, смогу ли я это исправить. - person Harriv; 03.02.2009
comment
Я не говорю, что вы должны реализовать это именно так, просто разработать рабочее решение и отладить его будет намного проще. Конечно, вы можете просто сохранить то, что у вас есть прямо сейчас, и создать новый модуль данных, предназначенный для использования в фоновом потоке. - person mghie; 03.02.2009