Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2010.10.31;
Скачать: CL | DM;

Вниз

сервис и ADO (многопотоковый COM)   Найти похожие ветки 

 
truegosha   (2007-01-19 16:33) [0]

Объясню название темы моего сообщения. ADO ведь реализовано как COM объект. Поэтому решил обратиться именно сюда, а не в форум по базам. Ошибка очень специфичная. Но может кто сталкивался...
На Delphi 6 писал службу с использованием API-функций. Служба эта - сервер приложений, среднее звено в трехзвенке. База MSSQL 2000. Служба многопоточная - главный поток, рабочий поток и следящий за рабочим. Рабочий поток создавал так:
hWorkTread := CreateThread(nil, 0, @ServerProc, @StatusHandle, 0, Dummy);

Вот процедура рабочего потока:
procedure ServerProc (Param: Pointer); stdcall;
var
 WorkThrStuff: TWorkThrStuff;
 client: TSimpleClient;
 cIE: HResult;
begin
 cIE := CoInitializeEx(nil, COINIT_MULTITHREADED);
 WorkThrStuff := TWorkThrStuff.Create;
 while bWork do
 begin
   if counter = 60 then
   begin
     client := nil;
     WorkThrStuff.RefreshState(client);
     counter := 1;
   end
   else counter := counter + 1;
   Sleep(1000);
 end;
 WorkThrStuff.Destroy;
 if Succeeded(cIE) then CoUninitialize;
end;

Вот кусок главного потока, который обрабатывает запросы SCM:
 while Status.dwCurrentState <> SERVICE_STOPPED do
 begin
   if not firsttime then
   begin
     if fdwControl = SERVICE_CONTROL_INTERROGATE then NotifyState
     else if dwSrvCtrlToPend[fdwControl] <> 0 then
     begin
       NotifyPend(fdwControl);
       if dwSrvCtrlToPend[fdwControl] = SERVICE_STOP_PENDING then
       begin
         bWork := false;
         if WaitForSingleObject(hControlTread, INFINITE) <> WAIT_OBJECT_0 then
         begin
           MyMsg[0]:="Остановка выполняется с ошибкой!";
           ReportEvent(EventLog, EVENTLOG_WARNING_TYPE, 0, 0, nil, 1, 0, @MyMsg, nil);
         end
         else
         begin
           CloseHandle(hControlTread);
           hControlTread := 0;
         end;
         if WaitForSingleObject(hWorkTread, INFINITE) <> WAIT_OBJECT_0 then
         begin
           MyMsg[0]:="Остановка выполняется с ошибкой!";
           ReportEvent(EventLog, EVENTLOG_WARNING_TYPE, 0, 0, nil, 1, 0, @MyMsg, nil);
         end
         else
         begin
           CloseHandle(hWorkTread);
           hWorkTread := 0;
         end;
       end;
       if dwSrvPendToState[Status.dwCurrentState] <> 0 then NotifyState;
     end;
   end;
   if bWork and (fdwControl = WORKTHREAD_CRASH) then
   begin
     MyMsg[0]:="Рабочий поток упал! Перезапуск потока!";
     ReportEvent(EventLog, EVENTLOG_ERROR_TYPE, 0, 0, nil, 1, 0, @MyMsg, nil);
     counter := 1;
     hWorkTread := CreateThread(nil, 0, @ServerProc, @StatusHandle, 0, Dummy);
   end;
   if Status.dwCurrentState <> SERVICE_STOPPED then
   begin
     GetQueuedCompletionStatus(g_hIOCP, dwBytesTransferred, fdwCompKey, po, INFINITE);
     fdwControl := dwBytesTransferred;
     firsttime := false;
   end;
 end;

В рабочем потоке полным-полно ADO компонентов. Причем для каждого клиентского приложения, подключающегося к серверу, в рабочем потоке создается свой поток. Поэтому вызываю CoInitializeEx(nil, COINIT_MULTITHREADED);
А при выходе из рабочего потока вызываю if Succeeded(cIE) then CoUninitialize;
На Windows 2000 работает без ошибок. А на XP после остановки службы выдается ошибка в модуле unknown. Как я понимаю, unknown - это интерфейс COM.
Где-то читал, что CoUninitialize нужно вызывать только для процесса, а не для потоков. Пробовал и так. Вызывал в самом конце программы. Не помогло. Заказчик, как на зло собирается ставить службу на XP.
Уже все варианты что знал - перебрал. Помогите пожалуйста! Заранее спасибо!


 
tesseract ©   (2007-01-21 13:14) [1]

> Как я понимаю, unknown - это интерфейс COM.

iUnknown  - это базовый интерфейс, существует во всем COM-объектах. Попробуй отладчиком посмотреть, где ошибка.


 
Polevi ©   (2007-01-23 08:05) [2]

попробуй убрать
if Succeeded(cIE) then CoUninitialize;


 
Сергей М. ©   (2007-01-23 10:41) [3]


> Рабочий поток создавал так:
> hWorkTread := CreateThread(


Нельзя так делать.
Рано или поздно при таком способе нахватаешь "глюков" по самое нехочу.

Используй BeginThread().


 
truegosha   (2007-01-24 10:01) [4]

Спасибо всем за ответы!
BeginThread() помогло!!!



Страницы: 1 вся ветка

Текущий архив: 2010.10.31;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.007 c
6-1228215284
dmitry_12_08_73
2008-12-02 13:54
2010.10.31
Передача файла с помощью компонента TIdHTTP


2-1280982633
PinDOS
2010-08-05 08:30
2010.10.31
Символы определенные компилятором


15-1279890684
aka
2010-07-23 17:11
2010.10.31
Сетевая игра


2-1280939572
istok
2010-08-04 20:32
2010.10.31
навигация по TADOStoredProc...


2-1281417193
И. Павел
2010-08-10 09:13
2010.10.31
Два почти одинаковых запроса выполняются по разному