Конференция "Базы" » Удаление TADOConnection в потоке [D7, MSSQL]
 
  • Артем (02.08.11 21:40) [0]
    Здравствуйте мастера!
    Проблема в том что нужно удалять соединения в потоке.

    Вот примерный код потока:


    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 может не пройти по каким-либо причинам, и соединение подвисает, а при уничтожении соединения и основной поток, поэтому уничтожение убрано в отдельный поток.

    Помогите кто-нибудь, кто сталкивался с подобным.
  • sniknik © (02.08.11 22:19) [1]
    ADO соединение это вообще то COM объект... и он может не уничтожаться, а ждать какое то время следующего, если они быстро друг за другом идут, это ускоряет процесс.

    но у тебя и без "тонкостей" ошибок хватает...
    используешь поток как список объектов "из вне" потока... странно. ссылка на объект в 2 местах минимум...
    объект (vcl) не "убивается", а просто удаляется из списка... еще более странно. а говоришь уничтожается... где?
    наверное в "..." или в "...", хотя нет в "...", или не так,  а так "все переписать нафиг" все, что стесняешься показать это один большой глюк.

    +
    нет надобности в потоках, есть асинхронный режим, там он сам потоками "рулит".

    > Помогите кто-нибудь, кто сталкивался с подобным.
    шутишь? подобного не повторить... где уж столкнуться.
  • Ega23 © (02.08.11 23:32) [2]

    > объект (vcl) не "убивается", а просто удаляется из списка.


    У него же TObjectList, а не TList
    Хотя в целом - безусловно говнокод
  • знайка (02.08.11 23:49) [3]

    > Хотя в целом - безусловно говнокод
    так это, продемонстрируете мастер-код? а ту поржут... а?
  • Игорь Шевченко © (03.08.11 00:10) [4]
  • Артем (03.08.11 05:38) [5]
    TObjectLIst сам освобождает память при удалении объекта из списка.
  • Вариант (03.08.11 07:24) [6]

    > Артем   (02.08.11 21:40)
    >
    > Соединения надо удалять так, потому что сединение с СУБД
    > MsSQL может не пройти по каким-либо причинам, и соединение
    > подвисает, а при уничтожении соединения и основной поток,
    >  поэтому уничтожение убрано в отдельный поток.

    Реализация работы с потоком сделана неверно. Критическая секция ничего не защищает, да и сам поток не нужен ибо ->
    "Кто к нам с мечом придет, тот от меча и погибнет" (С) к/ф "Александр Невский" -расшифрую,  тот поток, в котором был создан TADOConnection  будет "висеть" в любом случае, если зависнет TADOConnection, в каком бы ты потоке его не закрывал(освобождал).
  • Артем (03.08.11 07:34) [7]

    > > Артем   (02.08.11 21:40)
    > >
    > > Соединения надо удалять так, потому что сединение с СУБД
    > > MsSQL может не пройти по каким-либо причинам, и соединение
    > > подвисает, а при уничтожении соединения и основной поток,
    >
    > >  поэтому уничтожение убрано в отдельный поток.
    >
    > Реализация работы с потоком сделана неверно. Критическая
    > секция ничего не защищает, да и сам поток не нужен ибо -
    > >
    > "Кто к нам с мечом придет, тот от меча и погибнет" (С) к/ф
    > "Александр Невский" -расшифрую,  тот поток, в котором был
    > создан TADOConnection  будет "висеть" в любом случае, если
    > зависнет TADOConnection, в каком бы ты потоке его не закрывал(освобождал).
    >


    Поток в котором создается TADOConnection не подвиснет (сделано так чтоб не подвисал)
  • Вариант (03.08.11 07:49) [8]

    > Артем   (03.08.11 07:34) [7]

    Кем сделано? Почитай про COM объекты , апартаменты....
  • Артем (03.08.11 08:02) [9]
    Мной сделано. Главное что поток не подвиснет при подключении/отключении.
    Но подвиснет при уничтожении соединения. Как его лучше уничтожить, чтобы не завис поток?
  • sniknik © (03.08.11 08:03) [10]
    > У него же TObjectList, а не TList
    ;( не обратил внимания.

    > так это, продемонстрируете мастер-код? а ту поржут... а?
    писать просто так? абстрактный код? ... даже попытка достойна ржача.
    - "когда у общества нет цветовой дифференциации штанов, то нет цели! А когда нет цели…" © Кин-Дза-Дза
    в смысле, код должен иметь цель, а код без цели лишен смысла...

    > Поток в котором создается TADOConnection не подвиснет (сделано так чтоб не подвисал)
    > CoInitialize и CoUninitialize никак не помогают.
    они рассчитаны на  поток, и обязательны для каждого потока, т.е. сначала инициализируется COM модель, после в нем создается COM объект. а у тебя, "твоя модель" совсем не работает, т.к. "завязки" у обьекта на другой поток.

    p.s. если ты уверен, что все правильно, и все отвергаешь, то тебе не сюда, тебе в микрософт писать нужно... вот, что за фигня, написали операционку не совместимую с твоей программой...
  • Артем (03.08.11 08:14) [11]

    > p.s. если ты уверен, что все правильно, и все отвергаешь,
    >  то тебе не сюда, тебе в микрософт писать нужно... вот,
    > что за фигня, написали операционку не совместимую с твоей
    > программой...


    Я сюда и написал, потому что не уверен что правильно сделал.
    В общем, мне надо чтобы так было:
    Основной поток, например по таймеру, соединяется с БД, выполняет запросы и т.д. (при соединении поток не зависнет, даже если нет физического соединения с сервером, но зависнет при уничтожении).
    Как уничтожить соединение чтобы основной поток не завис (или если вынести в отдельный поток работу с БД чтобы этот поток не зависал)?
  • Вариант (03.08.11 08:32) [12]

    > Артем   (03.08.11 08:02) [9]


    > Мной сделано

    В таком варианте не поможет.

    >  Как его лучше уничтожить, чтобы не завис поток?

    Если речь про основной поток, то например создавать, работать и уничтожать соединение и/или другие ADO компоненты в одном дополнительном потоке. Кстати тогда возможно все ограничится TADOCommand для доп. потока. Пусть висит доп. поток. Отвиснет, возникнет ошибка - передашь ее в основной поток. И еще в этом случае придется решать проблемы корректной передачи результатов запроса из одного потока в другой. Или смириться тем, что при ошибках в соединении возможно подвисание пользовательского интерфейса, но работать в основном потоке и не иметь других проблем.  Тут тебе видней.
  • Артем (03.08.11 08:47) [13]
    Работа с БД не связана с пользовательским интерфейсом, она вообще должна идти фоново. А подвисание потока, в котором выполняются запросы, недопустимо. Например, если нет соединения с СУБД, но есть с самим компьютером то подвиснет ненадолго (на время таймаута, заданного в adoconnection'е), или если нет связи с компьютером, то зависнут может надолго (у меня было и по 2-3 минуты). Для работы программы даже подвисания на 10 сек. недопустимы.

    Вот я и хочу, чтобы в основном потоке выполнялось соединение, выполнялись запросы, а сам adoconnection уничтожался бы в другом, чтобы основной не подвисал в случае отсутствия связи.
  • sniknik © (03.08.11 09:30) [14]
    > Как уничтожить соединение чтобы основной поток не завис (или если вынести в отдельный поток работу с БД чтобы этот поток не зависал)?
    сделать все независимым от основного, "от а до я", и в этом случае совершенно неважно, что какой то из потоков "завис".
    > она вообще должна идти фоново.
    о!!!
    > А подвисание потока, в котором выполняются запросы, недопустимо.
    с чего это если используется синхронный режим (совет про асинхронный ты проигнорировал) и есть вполне уместный таймаут (это не зависание) от обязательного завершения операции (дать ответ).

    > уничтожался бы в другом, чтобы основной не подвисал в случае отсутствия связи.
    "висит" (тут это неправильное слово) не уничтожение, а ожидание выполняемой операции, пасть даже результатом таймаут, а операция у тебя выполняется где?...
  • sniknik © (03.08.11 09:33) [15]
    > пасть
    пусть

    кстати а что вообще за бредовая идея уничтожать коннект в процессе работы? ели он постоянно нужен. а если не нужен... ну пусть себе "повисит" дополнительный поток, не связанный с основным... чем он мешает то?
  • Артем (03.08.11 09:45) [16]

    > кстати а что вообще за бредовая идея уничтожать коннект
    > в процессе работы? ели он постоянно нужен. а если не нужен.
    > .. ну пусть себе "повисит" дополнительный поток, не связанный
    > с основным... чем он мешает то?


    Если соединение не проходит (коннект завис или еще что-то), то его надо уничтожить. А ждать пока пройдут все таймуаты нельзя. CommandTimeOut и ConnectionTimeout не срабатывают если нет физического соединения с компьютером, на котором работает MSSQL Server (просто к сети не подключен или вообще выключен), в остальных они срабатывают.
  • Anatoly Podgoretsky © (03.08.11 09:53) [17]
    > Артем  (03.08.2011 09:45:16)  [16]

    > А ждать пока пройдут все таймуаты нельзя.

    Тогда откуда ты решил, что соединение не проходит?
  • Артем (03.08.11 10:02) [18]
    Есть функция, которая делает соединение с помощью дополнительного потока.
    В функцию передаются ссылка на коннект и таймаут.
    Функция создает поток, передает в поток коннект. Потом в цикле проверяет значение флажка в потоке, и если в течение времени таймаута не флажек False, то поток убивается, функция возвращает False. Или True если флажек стал True до истечения таймаута.

    Если функция возвращает false, то он передается в другой поток на уничтожение, чтобы основной поток не задерживать своими таймаутами. В этом другом потоке коннект и должен уничтожаться.
  • sniknik © (03.08.11 11:56) [19]
    > CommandTimeOut и ConnectionTimeout не срабатывают
    ???? у тебя, что пятая дельфя? только там, да и то без обновлений, была проблема с таймаутами. хотя, решаемая, правда через генофонд.

    > В этом другом потоке коннект и должен уничтожаться.
    он там, или оттуда у тебя и уничтожается, но таймаут от операции все одно останется на операции, и с этим ничего в синхронном режиме не поделать.

    > Есть функция .... бла.бла.бла.
    меньше слов больше дел.. кода!
 
Конференция "Базы" » Удаление TADOConnection в потоке [D7, MSSQL]
Есть новые Нет новых   [134431   +10][b:0][p:0.001]