Конференция "Базы" » Удаление 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 не срабатывают
    ???? у тебя, что пятая дельфя? только там, да и то без обновлений, была проблема с таймаутами. хотя, решаемая, правда через генофонд.

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

    > Есть функция .... бла.бла.бла.
    меньше слов больше дел.. кода!
  • Артем (03.08.11 12:25) [20]

    > > CommandTimeOut и ConnectionTimeout не срабатывают
    > ???? у тебя, что пятая дельфя? только там, да и то без обновлений,
    >  была проблема с таймаутами. хотя, решаемая, правда через
    > генофонд.


    Пробовал в седьмой дельфи и XE, все равно не срабатывает таймаут.


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

    Если я отправил коннект на уничтожение, то мне уже без разницы что он подвис.


    > > Есть функция .... бла.бла.бла.
    > меньше слов больше дел.. кода!

    Зачем тебе код этой функции?
    У меня был вопрос почему после уничтожения коннекта остаются User Handles.
  • DiamondShark © (03.08.11 12:27) [21]

    > sniknik ©   (03.08.11 11:56) [19]
    > > CommandTimeOut и ConnectionTimeout не срабатывают????
    > у тебя, что пятая дельфя?

    При чём здесь пятая дельфя? Он говорит про случай физической недоступности компьютеров. Здесь ни при чём не только дельфя, но и ни АДО ни МССКЛ дбпровайдер, ни дблиб. Это фича сокетов. Ну нету никакой возможности прервать сокетный connect(), ждущий ответа от недоступного хоста. Нету, хоть ты тресни.

    Инфа 100%, что при недоступности хоста ConnectionTimeout курит в углу, а управление возвращается, когда TCP-стек соблаговолит. Так себя ведёт и АДО с МССКЛ дбпровайдером, и ОДБЦ драйвер, дотНЕТ-клиент.
    А всё, сцуко, потому, что все они, в конце-концов, вызывают синхронный сокетный connect().
  • DiamondShark © (03.08.11 12:32) [22]

    > У меня был вопрос почему после уничтожения коннекта остаются
    > User Handles.

    А что такое, по-твоему, User Handles?
    Ну, вот, например, подсистема СОМ создаёт невидимые окна для обслуживания маршалинга. Окно -- это один из типов User Handle. Оно тебя сильно волнует?
  • DiamondShark © (03.08.11 12:43) [23]

    > Артем   (03.08.11 10:02) [18]

    Неправильно.

    Сделай функцию, которая принимает строку подключения, а вернуть должна экземпляр коннекта.
    Пусть функция создаёт экземпляр коннекта, настраивает параметры подключения и передаёт экземпляр в поток для открытия соединения.
    Потом функция пусть отсчитывает таймаут, и если поток не завершился, то устанавливает потоку флажок "коннект уже не нужен, удавись", и возвращяет NIL.

    А поток пусть ждёт подключения хоть до морковкина заговенья. Когда процедура потока получит возврат управления из Connection.Open(), она проверит флажок, если он сброшен, то просто оставит экзкмпляр коннекта в покое, а если установлен, то закроет соединение и разрушит экземпляр коннекта.
    В обоих исходах поток, в конце-концов, самоубъётся апстену.

    Не надо никаких разных потоков для подключения и уничтожения коннектов.
  • sniknik © (03.08.11 12:43) [24]
    > Зачем тебе код этой функции?
    ни этой, ни другой не нужно. нужно то что покажет реализацию полностью, хоть вообще без фунций

    > У меня был вопрос почему после уничтожения коннекта остаются User Handles.
    тебе ответили. нет закрытия без ожидания завершения операции, а если уничтожать "насильно" терминейтом то там вообще все будет не завершено, не освобождено.
    + таймаут, на "предвидение" очередного конекта в ту же сторону. стандартное поведение ADO.

    > При чём здесь пятая дельфя?
    в пятой не работало.
    > Он говорит про случай физической недоступности компьютеров.
    ну вот стоит у меня 30 сек, доступен, не доступен сервер мне не важно, через 30 отвалится - "кончилось время".  

    > Нету, хоть ты тресни.
    а зачем его прерывать? этого не нужно, сокеты всегда в своих потоках, имхо, все что ему нужно это дать ответ "ожидающему концу" через 30 сек.
    и опять имхо, именно так оно и работает. (не встречался с другим поведением... исключая 5ю дельфю)
  • Артем (03.08.11 12:48) [25]

    > А что такое, по-твоему, User Handles?
    > Ну, вот, например, подсистема СОМ создаёт невидимые окна
    > для обслуживания маршалинга. Окно -- это один из типов User
    > Handle. Оно тебя сильно волнует?

    Если честно, то я даже и не знаю что именно подразумевается под User Handles в Process Explorer.
    А так да, волнуют. Моя программа должна работать по несколько недель подряд. Представь себе сколько их накопится за это время, после этого наверное ОС сдохнет.

    Для эксперимента вызывал в AddObject сразу FreeAndNil(Obj). Коннект нормально удалился, хендлы тоже удалились. Также пробовал делать FObjList.Add(Obj), а потом FObjList.Delete(0), тоже все нормально удалилось. Но вот почему в процедуре Execute не так все хорошо удаляется.
  • Артем (03.08.11 12:50) [26]

    > Неправильно.
    >
    > Сделай функцию, которая принимает строку подключения, а
    > вернуть должна экземпляр коннекта.
    > Пусть функция создаёт экземпляр коннекта, настраивает параметры
    > подключения и передаёт экземпляр в поток для открытия соединения.
    >
    > Потом функция пусть отсчитывает таймаут, и если поток не
    > завершился, то устанавливает потоку флажок "коннект уже
    > не нужен, удавись", и возвращяет NIL.
    >
    > А поток пусть ждёт подключения хоть до морковкина заговенья.
    >  Когда процедура потока получит возврат управления из Connection.
    > Open(), она проверит флажок, если он сброшен, то просто
    > оставит экзкмпляр коннекта в покое, а если установлен, то
    > закроет соединение и разрушит экземпляр коннекта.
    > В обоих исходах поток, в конце-концов, самоубъётся апстену.
    >
    >
    > Не надо никаких разных потоков для подключения и уничтожения
    > коннектов.

    Спасибо, попробую.
  • sniknik © (03.08.11 13:00) [27]
    > Но вот почему в процедуре Execute не так все хорошо удаляется.
    другой поток, не инициализирована COM модель, обьект завязан на "чужую"... что хорошего может быть?

    > Спасибо, попробую.
    а нормально, на асинхронной/событийной логике слабо?
  • Артем (03.08.11 14:08) [28]
    unit ConnThread;

    interface

    uses
     Classes, ADODB, SysUtils, InterfacedThread, Windows, ActiveX;

    type
     TConnThread = class(TInterfacedThread)
     public
       Connection:TADOConnection;
       Connected:boolean;
       ConnectionString:string;
       FM:boolean; //из основного потока по
                   //этой переменной узнает что подключение есть
       destructor Destroy;  override;
       constructor Create(T:Boolean);
     private
       Flag:Boolean;
       { Private declarations }
     protected
       procedure Execute; override;
     published
     end;

    implementation

    constructor TConnЕhread.Create(T: Boolean);
    begin
     inherited;
     Flag:=False;
     CoInitialize(nil);
     Connection:=TADOConnection.Create(nil);
    end;

    destructor TConnThread.Destroy;
    begin
     if not Flag then
       if Assigned(Connection) then
         FreeAndNil(Connection);
     CoUninitialize;
     inherited;
    end;

    procedure TConnThread.Execute;
    begin
     try
       FM:=False;
       if Connected then
         Connection.Connected:=True
       else
         Connection.Connected:=False;
       FM:=True;
     except
     end;
    end;

    end.



    Все равно не удаляются хендлы. FreeOnTerminate стоит True.
  • sniknik © (03.08.11 14:16) [29]
    > //из основного потока по
    > //этой переменной узнает что подключение есть
    по данному коду его вообще никогда не будет... можно не парится с узнаванием.

    +
    создание потока и деструктор делаются в основном потоке вообще то... т.что в принципе ты ничего не изменил.

    ++
    а где Free?
  • sniknik © (03.08.11 14:18) [30]
    > а где Free?
    а, нашел.
  • Артем (03.08.11 15:09) [31]
    Поток создается в основном потоке, тут я только код самого потока подключения привел как советовал DiamondShark.


    > создание потока и деструктор делаются в основном потоке
    > вообще то... т.что в принципе ты ничего не изменил.

    Деструктор чего, потока или коннекта. Если потока, то для этого FreeOnTerminate в True установлено. Деструктор будет вызван когда закончиться выполнение процедуры Execute.
  • sniknik © (03.08.11 15:57) [32]
    > Если потока, то для этого FreeOnTerminate в True установлено.
    при чем здесь FreeOnTerminate,  у тебя опять CoInitialize делается не в том потоке в котором используется...
  • sniknik © (03.08.11 16:02) [33]
    вот для примера
    unit ConnThread;

    interface

    uses
    Classes, ADODB, SysUtils, Windows, ActiveX;

    type
     TConnThread = class(TThread)
     private
       Connection: TADOConnection;
     protected
       procedure Execute; override;
     public
       destructor Destroy;  override;
       constructor Create(CreateSuspended: Boolean);
     end;

    implementation

    constructor TConnThread.Create(CreateSuspended: Boolean);
    begin
     inherited;

     //CoInitialize(nil);
     //Connection:= TADOConnection.Create(nil);

     FreeOnTerminate:= true;
     Resume;
    end;

    destructor TConnThread.Destroy;
    begin
     //FreeAndNil(Connection);
     //CoUninitialize;

     inherited;
    end;

    procedure TConnThread.Execute;
    begin
     CoInitialize(nil);
     try
       Connection:= TADOConnection.Create(nil);
       FreeAndNil(Connection);
     finally
       CoUninitialize;
     end;
    end;

    end.



    и выполнить, до абсурда  

    uses ConnThread;

    procedure TForm1.Button1Click(Sender: TObject);
    var
     i: integer;
    begin
     for i:= 1 to 1000 do
       TConnThread.Create(true);
    end;



    работает?
    а теперь закоментарь внутри Execute и раскоментарь в деструкторе/конструкторе... работает? или AV? (что возможно при "пересечениях" потоков. ну или у тебя очень быстрый комп... успевает, добавь нагрузку в Execute).
  • sniknik © (03.08.11 16:05) [34]
    > TConnThread = class(TThread)
    ???
    а как же декларируемая независимость от основного потока?
  • Игорь Шевченко © (03.08.11 18:14) [35]

    > у тебя опять CoInitialize делается не в том потоке в котором
    > используется


    мне кажется, должно быть CoInitializeEx (...COINIT_MULTITHREADED)
  • Артем (03.08.11 18:22) [36]

    > работает? а теперь закоментарь внутри Execute и раскоментарь
    > в деструкторе/конструкторе... работает? или AV? (что возможно
    > при "пересечениях" потоков. ну или у тебя очень быстрый
    > комп... успевает, добавь нагрузку в Execute).

    У меня и раньше память высвобождалась занятая коннектом, количество хендлов оставалось, прежним. При создании увеливались, а при уничтожении не удалялись.


    > мне кажется, должно быть CoInitializeEx (...COINIT_MULTITHREADED)

    Спасибо, надо почитать мануалы.
  • sniknik © (03.08.11 20:45) [37]
    > мне кажется, должно быть CoInitializeEx (...COINIT_MULTITHREADED)
    без разницы
    http://msdn.microsoft.com/en-us/library/ms695279%28v=vs.85%29.aspx
    ...
    The concurrency model and initialization options for the thread. Values for this parameter are taken from the COINIT enumeration. Any combination of values from COINIT can be used, except that the COINIT_APARTMENTTHREADED and COINIT_MULTITHREADED flags cannot both be set. The default is COINIT_MULTITHREADED.
    ...
    Because OLE technologies are not thread-safe, the OleInitialize function calls CoInitializeEx with the COINIT_APARTMENTTHREADED flag. As a result, an apartment that is initialized for multithreaded object concurrency cannot use the features enabled by OleInitialize.
    ...
    т.е. любом случае не обслуживает несколько потоков одной инициализацией, фактически VCL от мелкософта... ;)

    > У меня и раньше память ... бла.бла.бла.
    чем дальше, тем больше ощущение, что я тебе "про бабушку", а ты все "про дедушку" (уж куда более очевидно, проверил, да/нет ситуация такая, нет опять фигню свою несет)... и кому это надо? парься сам.
  • sniknik © (03.08.11 21:11) [38]
    Игорь Шевченко ©   (03.08.11 18:14) [35]
    можно чуток изменить тест, чтобы уж "по любому". на AV нарваться тут "дело техники", а вот так гарантированный глюк должен быть -
    unit ConnThread;

    interface

    uses
     Classes, ADODB, SysUtils, Windows, ActiveX;

    type
     TConnThread = class(TThread)
     private
       Connection: TADOConnection;
     protected
       procedure Execute; override;
     public
       destructor Destroy;  override;
       constructor Create(CreateSuspended: Boolean);
     end;

    implementation

    constructor TConnThread.Create(CreateSuspended: Boolean);
    begin
     inherited;

     //CoInitialize(nil);
     CoInitializeEx(nil, COINIT_MULTITHREADED);
     Connection:= TADOConnection.Create(nil);

     FreeOnTerminate:= true;
     Resume;
    end;

    destructor TConnThread.Destroy;
    begin
     FreeAndNil(Connection);
     CoUninitialize;

     inherited;
    end;

    procedure TConnThread.Execute;
    begin
     {CoInitialize(nil);
     try
       Connection:= TADOConnection.Create(nil);}


       //Connection.ConnectionString:= 'Provider=SQLOLEDB.1;Integrated Security=SSPI'; //mssql ëîêàëüíî
       Connection.ConnectionString:= 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\;Extended Properties=Text'; //Jet
       Connection.Connected:= true;

     {  FreeAndNil(Connection);
       Sleep(0);
     finally
       CoUninitialize;
     end;}

    end;

    end.


    что делать понятно... 2 варианта.
  • Игорь Шевченко © (03.08.11 22:59) [39]
    sniknik ©   (03.08.11 20:45) [37]


    > без разницы


    CoInitialize calls CoInitializeEx and specifies the concurrency model as single-thread apartment.

    с разницей.


    > т.е. любом случае не обслуживает несколько потоков одной
    > инициализацией


    CoInitializeEx должна быть вызвана в самом потоке, который работает с OLE, COM, ADO, etc
  • sniknik © (04.08.11 00:02) [40]
    > с разницей.
    блин.
    - не ходите дети через дорогу на красный может сбить машиной!
    - а вроде тут ходят троллейбусы...
    - да без разницы чем собьет. убить может.
    - с разницей.
    типа машина на бензине, а троллейбусы на электричестве... и это ОЧЕНЬ важно, просто чтобы возразить. хотя говорили о другом.

    > CoInitializeEx должна быть вызвана в самом потоке, который работает с OLE, COM, ADO, etc
    а я о чем? с самого начала. ты читай, что пишут прежде чем возражать... повторенными словами оппонента.
  • OW © (04.08.11 09:40) [41]
    скажите, а
    procedure CoUninitialize;               external ole32 name 'CoUninitialize';
    обязательно вызывать, если поток где я вызываю CoInitializeEx(nil, 0); мне больше не нужен?
  • sniknik © (04.08.11 11:17) [42]
    по msdn вызовы должны быть строго парные. освобождение ресурсов...
    т.е. раз вызвал CoInitialize то неважно, что тебе нужно, должен вызвать и CoUninitialize.
 
Конференция "Базы" » Удаление TADOConnection в потоке [D7, MSSQL]
Есть новые Нет новых   [134431   +10][b:0.001][p:0.006]