![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поведение ADOConnection в многопоточном приложении [MSSQL]
Ega23 © (2005-11-08 16:46:00)Ситуация следующая:
Есть некая система с достаточно большим количеством объектов. У каждого из объектов есть поле Status, и это свойство изменяется в реальном времени по неким событиям (как из пользовательского интерфейса, так, например, и по сетевому событию). Каждый из этих объектов имеет своё отображение в БД.
Теоретически, событие обновления статуса объекта должно происходить по-принципу "плюнул и забыл", т.е. не нужно дожидаться выполнения команды.
В реальной же жизни приложение всё-таки ждёт результат выполнения ADOQuery.ExecSQL, что естественно сказывается на времени обработки сообщения.
После некоторых раздумий было принято решение вынести обновления статусов объектов в отдельный поток. Но тут встала другая проблема: все запросы работают через один ADOConnection, у которого есть свойство State. И которое далеко не всегда только stOpen.
В связи с этим возникает вопрос: как можно обойти данную проблему? Плодить отдельный коннект на каждый поток? Проверять статус ADOConnection во всех потоках? Писать наследника от TADOQuery, где анализировать изменение ADOConnection.State?
В общем, поделитесь мыслями...
isasa (2005-11-08 17:56:00) [41]Silver Alex © (08.11.05 17:49) [6]
Один коннект на все приложение, один раз открыли при старте и при закрытии программы один раз закрыли.
А если потоков много. ISAPI, например.
Ega23 (2005-11-08 17:56:00) [42]
> 2. А почему-бы не воспользоваться напрямую TADOQuery.ConnectionString,
> минуя TADOConnection?
Да потому, что это на N запросов получается N коннектов. И на сервере у каждого из них СВОЙ ProcessID.
Silver Alex (2005-11-08 17:55:00) [43]>>Ega23 © (08.11.05 17:48) [5]
не понял, что такое прототип? обрисуй ситуации конкретней как-то, что за обьекты, что за события. Когда надо вызывать, что записывать в базу или читать. "Connection is busy" когда именно вываливается?не думаю что это TADOConnection, ни разу не встречал.Может сам сервер, хотя утверждать не буду. Надо больше информации
Ega23 (2005-11-08 17:54:00) [44]
> Один коннект на все приложение, один раз открыли при старте
> и при закрытии программы один раз закрыли. Или зачем тогда
> вообще это конекшен.
Вот-вот. Я тоже придерживаюсь такого мнения. Проблема в том, что основное приложение "сосёт" из БД различные выборки, причём достаточно часто. И при этом некая часть этого приложения (тот самый дополнительный поток) работает как "плюнул и забыл".
Сейчас в качестве промежуточного решения проблемы в дополнительном потоке вставлена проверка состояния ADOConnection. Если не stExecuting или stFetching - то пишем данные, иначе - ждём.
ANB (2005-11-08 17:53:00) [45]
> Ega23 © (08.11.05 17:50) [7]
В случае с ораклом при паралельной многопоточке я заводил отдельные сессии для каждого потока. Иначе - жуткие грабли. Для MS SQL я бы сделал так же.
isasa (2005-11-08 17:53:00) [46]1. Если инициализация ADO выполнена "по умолчанию" (с CoInitFlags=-1, модель STA), то по поводу потоков трудно что-то сказать.
2. А почему-бы не воспользоваться напрямую TADOQuery.ConnectionString, минуя TADOConnection?
Ega23 (2005-11-08 17:50:00) [47]
> Если нет необходимости работать с транзакциями, то можешь
> вобще без ADOConnecton обойтись. ADOQuery имеет собственный
> ConnectionString
> Или, как вариант, держать коннекцию постоянно открытой.
Коннект и так постоянно открыт. Его никто не закрывает.
А если для каждого ADOQuery свой коннект открывать... Это не есть гуд.
Silver Alex (2005-11-08 17:49:00) [48]>>Bronco © (08.11.05 17:43) [4]
>>которые открывают-закрывают коннекцию
парни, а вы что открываете-закрываете коннект с базой больше чем один раз? не советую вам так делать.Один коннект на все приложение, один раз открыли при старте и при закрытии программы один раз закрыли. Или зачем тогда вообще это конекшен.
Ega23 (2005-11-08 17:48:00) [49]
> Проблема выглядит какой-то надуманной.Не могу уловить, возможно
> не понял самой задачи.
Проблема в том, что при запуске прототипа было получено исключение, что-то типа: "Connection is busy". Ведь через этот коннект не только команды на обновление состояния идут.
Bronco (2005-11-08 17:43:00) [50]
> Ega23 © (08.11.05 17:28) [2]
Если нет необходимости работать с транзакциями, то можешь вобще без ADOConnecton обойтись. ADOQuery имеет собственный ConnectionString
Или, как вариант, держать коннекцию постоянно открытой.
В противном случае, те участки кода, которые открывают-закрывают коннекцию и работают с данными скорее всего придется защищать с помощью критических секций или чего-то еще.
Silver Alex (2005-11-08 17:40:00) [51]а в чем собственно сложность?и при чем здесь вообще ADOConnection.State? Наверное на каждый обьект(что за обьект, какой именно?) создавать поток и уже в нем(в потоке) производить свои вычисления.А несколько коннектов зачем, тоже не надо? Проблема выглядит какой-то надуманной.Не могу уловить, возможно не понял самой задачи.
Ega23 (2005-11-08 17:28:00) [52]
> WondeRu © (08.11.05 17:19) [1]
Не понял: у дополнительного потока всё-таки СВОЙ коннект, или нет? Или на приложение в целом создаётся отдельный поток, в котором идёт всё общение с базой?
WondeRu (2005-11-08 17:19:00) [53]Я бы сделал так:
Создается отдельный поток-обработчик, имеющий единственный ADOConnection. В этом потоке создается очередь (хоть TThreadList) сообщений от ваших объектов, которая постоянно (при наличии события в ней) записывается в БД.