![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Удаление TADOConnection в потоке [D7, MSSQL]
Артем © (2011-08-02 21:40:00)Здравствуйте мастера!
Проблема в том что нужно удалять соединения в потоке.
Вот примерный код потока:
type TMyThread= class(TThread);
....
FObjList: TObjectList;
Crit: TCriticalSection;
....
end;
constructor TMyThread.Create(CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
FObjList:= TObjectList.Create(True);
Crit:= TCriticalSection.Create;
end;
procedure TMyThread.AddObject(Obj: TADOConnection);
begin
Crit.Enter;
FObjList.Add(Obj);
Crit.Leave;
end;
procedure TMyThread.Execute;
begin
while not Terminated do
begin
sleep(10); //чтоб поток не грузил процессор
if FObjList.Count>0 then
FObjList.Delete(0);
end;
end;
//потом в основном потоке
...
var
T:TMyThread;
...
//поток создается и т.д.
...
//вызывается метод AddObject у потока
T.AddObject(Connection);
Прошелся дебагером по потоку объект вроде как уничтожается, но в ProcessExplorer'е увеливается счетик User Handles ровно на количество созданных мной соединений. CoInitialize и CoUninitialize никак не помогают.
Соединения надо удалять так, потому что сединение с СУБД MsSQL может не пройти по каким-либо причинам, и соединение подвисает, а при уничтожении соединения и основной поток, поэтому уничтожение убрано в отдельный поток.
Помогите кто-нибудь, кто сталкивался с подобным.
DiamondShark (2011-08-03 12:32:00) [21]
> У меня был вопрос почему после уничтожения коннекта остаются
> User Handles.
А что такое, по-твоему, User Handles?
Ну, вот, например, подсистема СОМ создаёт невидимые окна для обслуживания маршалинга. Окно -- это один из типов User Handle. Оно тебя сильно волнует?
DiamondShark (2011-08-03 12:27:00) [22]
> sniknik © (03.08.11 11:56) [19]
> > CommandTimeOut и ConnectionTimeout не срабатывают????
> у тебя, что пятая дельфя?
При чём здесь пятая дельфя? Он говорит про случай физической недоступности компьютеров. Здесь ни при чём не только дельфя, но и ни АДО ни МССКЛ дбпровайдер, ни дблиб. Это фича сокетов. Ну нету никакой возможности прервать сокетный connect(), ждущий ответа от недоступного хоста. Нету, хоть ты тресни.
Инфа 100%, что при недоступности хоста ConnectionTimeout курит в углу, а управление возвращается, когда TCP-стек соблаговолит. Так себя ведёт и АДО с МССКЛ дбпровайдером, и ОДБЦ драйвер, дотНЕТ-клиент.
А всё, сцуко, потому, что все они, в конце-концов, вызывают синхронный сокетный connect().
Артем (2011-08-03 12:25:00) [23]
> > CommandTimeOut и ConnectionTimeout не срабатывают
> ???? у тебя, что пятая дельфя? только там, да и то без обновлений,
> была проблема с таймаутами. хотя, решаемая, правда через
> генофонд.
Пробовал в седьмой дельфи и XE, все равно не срабатывает таймаут.
> > В этом другом потоке коннект и должен уничтожаться.
> он там, или оттуда у тебя и уничтожается, но таймаут от
> операции все одно останется на операции, и с этим ничего
> в синхронном режиме не поделать.
Если я отправил коннект на уничтожение, то мне уже без разницы что он подвис.
> > Есть функция .... бла.бла.бла.
> меньше слов больше дел.. кода!
Зачем тебе код этой функции?
У меня был вопрос почему после уничтожения коннекта остаются User Handles.
sniknik (2011-08-03 11:56:00) [24]> CommandTimeOut и ConnectionTimeout не срабатывают
???? у тебя, что пятая дельфя? только там, да и то без обновлений, была проблема с таймаутами. хотя, решаемая, правда через генофонд.
> В этом другом потоке коннект и должен уничтожаться.
он там, или оттуда у тебя и уничтожается, но таймаут от операции все одно останется на операции, и с этим ничего в синхронном режиме не поделать.
> Есть функция .... бла.бла.бла.
меньше слов больше дел.. кода!
Артем (2011-08-03 10:02:00) [25]Есть функция, которая делает соединение с помощью дополнительного потока.
В функцию передаются ссылка на коннект и таймаут.
Функция создает поток, передает в поток коннект. Потом в цикле проверяет значение флажка в потоке, и если в течение времени таймаута не флажек False, то поток убивается, функция возвращает False. Или True если флажек стал True до истечения таймаута.
Если функция возвращает false, то он передается в другой поток на уничтожение, чтобы основной поток не задерживать своими таймаутами. В этом другом потоке коннект и должен уничтожаться.
Anatoly Podgoretsky (2011-08-03 09:53:00) [26]> Артем (03.08.2011 09:45:16) [16]
> А ждать пока пройдут все таймуаты нельзя.
Тогда откуда ты решил, что соединение не проходит?
Артем (2011-08-03 09:45:00) [27]
> кстати а что вообще за бредовая идея уничтожать коннект
> в процессе работы? ели он постоянно нужен. а если не нужен.
> .. ну пусть себе "повисит" дополнительный поток, не связанный
> с основным... чем он мешает то?
Если соединение не проходит (коннект завис или еще что-то), то его надо уничтожить. А ждать пока пройдут все таймуаты нельзя. CommandTimeOut и ConnectionTimeout не срабатывают если нет физического соединения с компьютером, на котором работает MSSQL Server (просто к сети не подключен или вообще выключен), в остальных они срабатывают.
sniknik (2011-08-03 09:33:00) [28]> пасть
пусть
кстати а что вообще за бредовая идея уничтожать коннект в процессе работы? ели он постоянно нужен. а если не нужен... ну пусть себе "повисит" дополнительный поток, не связанный с основным... чем он мешает то?
sniknik (2011-08-03 09:30:00) [29]> Как уничтожить соединение чтобы основной поток не завис (или если вынести в отдельный поток работу с БД чтобы этот поток не зависал)?
сделать все независимым от основного, "от а до я", и в этом случае совершенно неважно, что какой то из потоков "завис".
> она вообще должна идти фоново.
о!!!
> А подвисание потока, в котором выполняются запросы, недопустимо.
с чего это если используется синхронный режим (совет про асинхронный ты проигнорировал) и есть вполне уместный таймаут (это не зависание) от обязательного завершения операции (дать ответ).
> уничтожался бы в другом, чтобы основной не подвисал в случае отсутствия связи.
"висит" (тут это неправильное слово) не уничтожение, а ожидание выполняемой операции, пасть даже результатом таймаут, а операция у тебя выполняется где?...
Артем (2011-08-03 08:47:00) [30]Работа с БД не связана с пользовательским интерфейсом, она вообще должна идти фоново. А подвисание потока, в котором выполняются запросы, недопустимо. Например, если нет соединения с СУБД, но есть с самим компьютером то подвиснет ненадолго (на время таймаута, заданного в adoconnection'е), или если нет связи с компьютером, то зависнут может надолго (у меня было и по 2-3 минуты). Для работы программы даже подвисания на 10 сек. недопустимы.
Вот я и хочу, чтобы в основном потоке выполнялось соединение, выполнялись запросы, а сам adoconnection уничтожался бы в другом, чтобы основной не подвисал в случае отсутствия связи.
Вариант (2011-08-03 08:32:00) [31]
> Артем (03.08.11 08:02) [9]
> Мной сделано
В таком варианте не поможет.
> Как его лучше уничтожить, чтобы не завис поток?
Если речь про основной поток, то например создавать, работать и уничтожать соединение и/или другие ADO компоненты в одном дополнительном потоке. Кстати тогда возможно все ограничится TADOCommand для доп. потока. Пусть висит доп. поток. Отвиснет, возникнет ошибка - передашь ее в основной поток. И еще в этом случае придется решать проблемы корректной передачи результатов запроса из одного потока в другой. Или смириться тем, что при ошибках в соединении возможно подвисание пользовательского интерфейса, но работать в основном потоке и не иметь других проблем. Тут тебе видней.
Артем (2011-08-03 08:14:00) [32]
> p.s. если ты уверен, что все правильно, и все отвергаешь,
> то тебе не сюда, тебе в микрософт писать нужно... вот,
> что за фигня, написали операционку не совместимую с твоей
> программой...
Я сюда и написал, потому что не уверен что правильно сделал.
В общем, мне надо чтобы так было:
Основной поток, например по таймеру, соединяется с БД, выполняет запросы и т.д. (при соединении поток не зависнет, даже если нет физического соединения с сервером, но зависнет при уничтожении).
Как уничтожить соединение чтобы основной поток не завис (или если вынести в отдельный поток работу с БД чтобы этот поток не зависал)?
sniknik (2011-08-03 08:03:00) [33]> У него же TObjectList, а не TList
;( не обратил внимания.
> так это, продемонстрируете мастер-код? а ту поржут... а?
писать просто так? абстрактный код? ... даже попытка достойна ржача.
- "когда у общества нет цветовой дифференциации штанов, то нет цели! А когда нет цели…" © Кин-Дза-Дза
в смысле, код должен иметь цель, а код без цели лишен смысла...
> Поток в котором создается TADOConnection не подвиснет (сделано так чтоб не подвисал)
> CoInitialize и CoUninitialize никак не помогают.
они рассчитаны на поток, и обязательны для каждого потока, т.е. сначала инициализируется COM модель, после в нем создается COM объект. а у тебя, "твоя модель" совсем не работает, т.к. "завязки" у обьекта на другой поток.
p.s. если ты уверен, что все правильно, и все отвергаешь, то тебе не сюда, тебе в микрософт писать нужно... вот, что за фигня, написали операционку не совместимую с твоей программой...
Артем (2011-08-03 08:02:00) [34]Мной сделано. Главное что поток не подвиснет при подключении/отключении.
Но подвиснет при уничтожении соединения. Как его лучше уничтожить, чтобы не завис поток?
Вариант (2011-08-03 07:49:00) [35]
> Артем (03.08.11 07:34) [7]
Кем сделано? Почитай про COM объекты , апартаменты....
Артем (2011-08-03 07:34:00) [36]
> > Артем (02.08.11 21:40)
> >
> > Соединения надо удалять так, потому что сединение с СУБД
> > MsSQL может не пройти по каким-либо причинам, и соединение
> > подвисает, а при уничтожении соединения и основной поток,
>
> > поэтому уничтожение убрано в отдельный поток.
>
> Реализация работы с потоком сделана неверно. Критическая
> секция ничего не защищает, да и сам поток не нужен ибо -
> >
> "Кто к нам с мечом придет, тот от меча и погибнет" (С) к/ф
> "Александр Невский" -расшифрую, тот поток, в котором был
> создан TADOConnection будет "висеть" в любом случае, если
> зависнет TADOConnection, в каком бы ты потоке его не закрывал(освобождал).
>
Поток в котором создается TADOConnection не подвиснет (сделано так чтоб не подвисал)
Вариант (2011-08-03 07:24:00) [37]
> Артем (02.08.11 21:40)
>
> Соединения надо удалять так, потому что сединение с СУБД
> MsSQL может не пройти по каким-либо причинам, и соединение
> подвисает, а при уничтожении соединения и основной поток,
> поэтому уничтожение убрано в отдельный поток.
Реализация работы с потоком сделана неверно. Критическая секция ничего не защищает, да и сам поток не нужен ибо ->
"Кто к нам с мечом придет, тот от меча и погибнет" (С) к/ф "Александр Невский" -расшифрую, тот поток, в котором был создан TADOConnection будет "висеть" в любом случае, если зависнет TADOConnection, в каком бы ты потоке его не закрывал(освобождал).
Артем (2011-08-03 05:38:00) [38]TObjectLIst сам освобождает память при удалении объекта из списка.
Игорь Шевченко (2011-08-03 00:10:00) [39]http://www.gunsmoker.ru/2008/10/x-y-z.html
знайка (2011-08-02 23:49:00) [40]
> Хотя в целом - безусловно говнокод
так это, продемонстрируете мастер-код? а ту поржут... а?