-
Здравствуйте мастера! Проблема в том что нужно удалять соединения в потоке. Вот примерный код потока:
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;
...
...
T.AddObject(Connection);
Прошелся дебагером по потоку объект вроде как уничтожается, но в ProcessExplorer'е увеливается счетик User Handles ровно на количество созданных мной соединений. CoInitialize и CoUninitialize никак не помогают. Соединения надо удалять так, потому что сединение с СУБД MsSQL может не пройти по каким-либо причинам, и соединение подвисает, а при уничтожении соединения и основной поток, поэтому уничтожение убрано в отдельный поток. Помогите кто-нибудь, кто сталкивался с подобным.
-
ADO соединение это вообще то COM объект... и он может не уничтожаться, а ждать какое то время следующего, если они быстро друг за другом идут, это ускоряет процесс.
но у тебя и без "тонкостей" ошибок хватает... используешь поток как список объектов "из вне" потока... странно. ссылка на объект в 2 местах минимум... объект (vcl) не "убивается", а просто удаляется из списка... еще более странно. а говоришь уничтожается... где? наверное в "..." или в "...", хотя нет в "...", или не так, а так "все переписать нафиг" все, что стесняешься показать это один большой глюк. + нет надобности в потоках, есть асинхронный режим, там он сам потоками "рулит".
> Помогите кто-нибудь, кто сталкивался с подобным. шутишь? подобного не повторить... где уж столкнуться.
-
> объект (vcl) не "убивается", а просто удаляется из списка.
У него же TObjectList, а не TList Хотя в целом - безусловно говнокод
-
> Хотя в целом - безусловно говнокод так это, продемонстрируете мастер-код? а ту поржут... а?
-
-
TObjectLIst сам освобождает память при удалении объекта из списка.
-
> Артем (02.08.11 21:40) > > Соединения надо удалять так, потому что сединение с СУБД > MsSQL может не пройти по каким-либо причинам, и соединение > подвисает, а при уничтожении соединения и основной поток, > поэтому уничтожение убрано в отдельный поток.
Реализация работы с потоком сделана неверно. Критическая секция ничего не защищает, да и сам поток не нужен ибо -> "Кто к нам с мечом придет, тот от меча и погибнет" (С) к/ф "Александр Невский" -расшифрую, тот поток, в котором был создан TADOConnection будет "висеть" в любом случае, если зависнет TADOConnection, в каком бы ты потоке его не закрывал(освобождал).
-
> > Артем (02.08.11 21:40) > > > > Соединения надо удалять так, потому что сединение с СУБД > > MsSQL может не пройти по каким-либо причинам, и соединение > > подвисает, а при уничтожении соединения и основной поток, > > > поэтому уничтожение убрано в отдельный поток. > > Реализация работы с потоком сделана неверно. Критическая > секция ничего не защищает, да и сам поток не нужен ибо - > > > "Кто к нам с мечом придет, тот от меча и погибнет" (С) к/ф > "Александр Невский" -расшифрую, тот поток, в котором был > создан TADOConnection будет "висеть" в любом случае, если > зависнет TADOConnection, в каком бы ты потоке его не закрывал(освобождал). >
Поток в котором создается TADOConnection не подвиснет (сделано так чтоб не подвисал)
-
> Артем (03.08.11 07:34) [7]
Кем сделано? Почитай про COM объекты , апартаменты....
-
Мной сделано. Главное что поток не подвиснет при подключении/отключении. Но подвиснет при уничтожении соединения. Как его лучше уничтожить, чтобы не завис поток?
-
> У него же TObjectList, а не TList ;( не обратил внимания.
> так это, продемонстрируете мастер-код? а ту поржут... а? писать просто так? абстрактный код? ... даже попытка достойна ржача. - "когда у общества нет цветовой дифференциации штанов, то нет цели! А когда нет цели…" © Кин-Дза-Дза в смысле, код должен иметь цель, а код без цели лишен смысла...
> Поток в котором создается TADOConnection не подвиснет (сделано так чтоб не подвисал) > CoInitialize и CoUninitialize никак не помогают. они рассчитаны на поток, и обязательны для каждого потока, т.е. сначала инициализируется COM модель, после в нем создается COM объект. а у тебя, "твоя модель" совсем не работает, т.к. "завязки" у обьекта на другой поток.
p.s. если ты уверен, что все правильно, и все отвергаешь, то тебе не сюда, тебе в микрософт писать нужно... вот, что за фигня, написали операционку не совместимую с твоей программой...
-
> p.s. если ты уверен, что все правильно, и все отвергаешь, > то тебе не сюда, тебе в микрософт писать нужно... вот, > что за фигня, написали операционку не совместимую с твоей > программой...
Я сюда и написал, потому что не уверен что правильно сделал. В общем, мне надо чтобы так было: Основной поток, например по таймеру, соединяется с БД, выполняет запросы и т.д. (при соединении поток не зависнет, даже если нет физического соединения с сервером, но зависнет при уничтожении). Как уничтожить соединение чтобы основной поток не завис (или если вынести в отдельный поток работу с БД чтобы этот поток не зависал)?
-
> Артем (03.08.11 08:02) [9]
> Мной сделано
В таком варианте не поможет.
> Как его лучше уничтожить, чтобы не завис поток?
Если речь про основной поток, то например создавать, работать и уничтожать соединение и/или другие ADO компоненты в одном дополнительном потоке. Кстати тогда возможно все ограничится TADOCommand для доп. потока. Пусть висит доп. поток. Отвиснет, возникнет ошибка - передашь ее в основной поток. И еще в этом случае придется решать проблемы корректной передачи результатов запроса из одного потока в другой. Или смириться тем, что при ошибках в соединении возможно подвисание пользовательского интерфейса, но работать в основном потоке и не иметь других проблем. Тут тебе видней.
-
Работа с БД не связана с пользовательским интерфейсом, она вообще должна идти фоново. А подвисание потока, в котором выполняются запросы, недопустимо. Например, если нет соединения с СУБД, но есть с самим компьютером то подвиснет ненадолго (на время таймаута, заданного в adoconnection'е), или если нет связи с компьютером, то зависнут может надолго (у меня было и по 2-3 минуты). Для работы программы даже подвисания на 10 сек. недопустимы.
Вот я и хочу, чтобы в основном потоке выполнялось соединение, выполнялись запросы, а сам adoconnection уничтожался бы в другом, чтобы основной не подвисал в случае отсутствия связи.
-
> Как уничтожить соединение чтобы основной поток не завис (или если вынести в отдельный поток работу с БД чтобы этот поток не зависал)? сделать все независимым от основного, "от а до я", и в этом случае совершенно неважно, что какой то из потоков "завис". > она вообще должна идти фоново. о!!! > А подвисание потока, в котором выполняются запросы, недопустимо. с чего это если используется синхронный режим (совет про асинхронный ты проигнорировал) и есть вполне уместный таймаут (это не зависание) от обязательного завершения операции (дать ответ).
> уничтожался бы в другом, чтобы основной не подвисал в случае отсутствия связи. "висит" (тут это неправильное слово) не уничтожение, а ожидание выполняемой операции, пасть даже результатом таймаут, а операция у тебя выполняется где?...
-
> пасть пусть
кстати а что вообще за бредовая идея уничтожать коннект в процессе работы? ели он постоянно нужен. а если не нужен... ну пусть себе "повисит" дополнительный поток, не связанный с основным... чем он мешает то?
-
> кстати а что вообще за бредовая идея уничтожать коннект > в процессе работы? ели он постоянно нужен. а если не нужен. > .. ну пусть себе "повисит" дополнительный поток, не связанный > с основным... чем он мешает то?
Если соединение не проходит (коннект завис или еще что-то), то его надо уничтожить. А ждать пока пройдут все таймуаты нельзя. CommandTimeOut и ConnectionTimeout не срабатывают если нет физического соединения с компьютером, на котором работает MSSQL Server (просто к сети не подключен или вообще выключен), в остальных они срабатывают.
-
> Артем (03.08.2011 09:45:16) [16]
> А ждать пока пройдут все таймуаты нельзя. Тогда откуда ты решил, что соединение не проходит?
-
Есть функция, которая делает соединение с помощью дополнительного потока. В функцию передаются ссылка на коннект и таймаут. Функция создает поток, передает в поток коннект. Потом в цикле проверяет значение флажка в потоке, и если в течение времени таймаута не флажек False, то поток убивается, функция возвращает False. Или True если флажек стал True до истечения таймаута.
Если функция возвращает false, то он передается в другой поток на уничтожение, чтобы основной поток не задерживать своими таймаутами. В этом другом потоке коннект и должен уничтожаться.
-
> CommandTimeOut и ConnectionTimeout не срабатывают ???? у тебя, что пятая дельфя? только там, да и то без обновлений, была проблема с таймаутами. хотя, решаемая, правда через генофонд.
> В этом другом потоке коннект и должен уничтожаться. он там, или оттуда у тебя и уничтожается, но таймаут от операции все одно останется на операции, и с этим ничего в синхронном режиме не поделать.
> Есть функция .... бла.бла.бла. меньше слов больше дел.. кода!
|