-
Объясню название темы моего сообщения. 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. Уже все варианты что знал - перебрал. Помогите пожалуйста! Заранее спасибо!
-
> Как я понимаю, unknown - это интерфейс COM.
iUnknown - это базовый интерфейс, существует во всем COM-объектах. Попробуй отладчиком посмотреть, где ошибка.
-
попробуй убрать if Succeeded(cIE) then CoUninitialize;
-
> Рабочий поток создавал так: > hWorkTread := CreateThread(
Нельзя так делать. Рано или поздно при таком способе нахватаешь "глюков" по самое нехочу.
Используй BeginThread().
-
Спасибо всем за ответы! BeginThread() помогло!!!
|