Additional
dbCAP
AnyDAC
ThinDAC
NCOCI8
Topic: inproc COM-сервер и AnyDAC
[1 2 |Next ]
inproc COM-сервер и AnyDAC
Posted: 2007/03/14 07:00
 
Привет.

Использую AnyDAC 1.10.0 под Д7 с MySQL 5.0.27.

Прект представляет из себя inproc COM-сервер (Apartment, SingleInstance).
Объект, обслуживаемый сервером, порождает единственный DataModule. Все вызовы компонентов AnyDAC синхронизированы единой CriticalSection. При закрытии любого клиента в

 TADPhysManager.InternalClose... lTimeOut := WaitForSingleObject(GClosedEvent...  

заканчивается таймаутом. Судя по монитору все компоненты и модуль уже удалены. Применение

 ADManager.Close

из примера использования AnyDAC в dll желаемого результата не принесло. На настоящий момент проблема решена так: в DataModuleDestroy добавлена строка

 (ADManager as IADPhysManager).Close(True)



Насколько это правильно и какие могут быть подводные камни?

С уважением. АК.
Re:inproc COM-сервер и AnyDAC
Posted: 2007/03/14 07:46
 
Привет

Попробуйте добавить в интерфейс сервера метод ReleaseEngine (или как еще назовете) и в его реализации вызывать ADManager.Close. В свою очередь метод ReleaseEngine сервера вызывайте перед тем, как отсоединиться от сервера.

Удачи,
Дмитрий
Re:inproc COM-сервер и AnyDAC
Posted: 2007/03/14 08:33
 
Привет.

Примерно так и делаю. В деструкторе СОМ-объекта вызывается деструктор datamodule, в DataModule.OnDestroy вызываю

 (ADManager as IADPhysManager).Close(True)

Отличие последнего от

 ADManager.Close

состоит в параметрах вызова

 procedure TADPhysManager.InternalClose(ATerminateAWaitForCloseBoolean);


Если AWaitForClose = True, то натыкаюсь на

 lTimeOut := WaitForSingleObject(GClosedEvent...  

Т.е. вызова

 procedure TADPhysManagerThread.SignalClosed;

не происходит (она вызывается из двух мест:

 destructor TADPhysManagerThread.Destroy;

и в

 procedure TADPhysManagerThread.DoIdle;

Почему так происхотит, я не разобрался. Это и вызывает беспокойство. Иначе говоря, можно ли вызывать (ADManager as IADPhysManager).Close(True) вместо ADManager.Close ?

PS. Не очень удобно, что письмо с уведомлением об ответе приходит без указания кодировки, хотя, возможно, это проблема почтового клиента.

С уважением. АК
Re:inproc COM-сервер и AnyDAC
Posted: 2007/03/14 08:51
 
Привет

(ADManager as IADPhysManager).Close(True) вместо ADManager.Close
Первое не есть корректно. Используйте ADPhysManager.Close(True). Его вы можете использовать вместо ADManager.Close.

Удачи,
Дмитрий
Re:inproc COM-сервер и AnyDAC
Posted: 2007/03/14 08:53
 
Пардон. ADManager не реализует IADPhysManager. Теперь я не знаю, как вызвать TADPhysManager.InternalClose(True, True); и избежать WaitForSingleObject
Re:inproc COM-сервер и AnyDAC
Posted: 2007/03/14 08:55
 
ADPhysManager.Close
Re:inproc COM-сервер и AnyDAC
Posted: 2007/03/14 13:45
 
Привет.

Увы, эти шаманства не помогают. Наблюдаю странную картину. При выполнении ADPhysManager.Close или ADManager.Free происходит отгрузка libmySQL.dll, после чего FManagerThread завершается (вижу в Event log). Судя по отладочному выводу TADPhysManagerThread.DoIdle проходит по ветке

 FManager.Closed; SignalClosed;

после чего возвращается в TADThread.Execute в FMessageEvent.WaitFor(FTimeout), откуда уже не выходит. Такое впечатление, что поток убивается извне.
Версия libmySQL.dll правильная, подгружается из /bin сервера.

Может быть, есть какие-нибудь гипотезы? Что еще можно проверить?

Пока. АК
Re:inproc COM-сервер и AnyDAC
Posted: 2007/03/14 13:45
 
Привет.

Проблема решена следующим образом: сразу после ADManager.Close вызываю ADTerminate. Напомню, что все это происходит в TDataModule.OnDestroy, а уничножение датамодуля - в деструкторе корневого СОМ-объекта. Надеюсь, побочных эффектов не будет.

Спасибо за участие.

Пока. АК

Post edited by: ak, at: 2007/03/15 20:45
Re:inproc COM-сервер и AnyDAC
Posted: 2007/03/23 03:24
 
Привет.

Я немного поспешил с заявлением, что проблема решена. Дело в том, что вызов ADTerminate затрагивает глобальные приватные переменные и является необратимым. Таким образом, его не следует вызывать из деструктора СОМ-объекта, т.к. СОМ-клиент в общем случае, удалив один объект, может создать новый.
Теперь напомню суть проблемы - между деструктором последнего СОМ-объекта и отгрузкой сервера (выполнения секций finalization) происходит принудительное удаление всех потоков, в том числе - TADPhysManager.FManagerThread, который на тот момент находится в состоянии ожидания (FMessageEvent.WaitFor(FTimeout)...). Такая ситуация кодом AnyDAC не предусматривается и

 lTimeOut := WaitForSingleObject(GClosedEventC_AD_PhysManagerShutdownTimeout) = WAIT_TIMEOUT;

в TADPhysManager.InternalClose завершается по таймауту. Сейчас я временно использую такую заплату: там же строку

 if FManagerThread <> nil then

расширил так

 if (FManagerThread <> nil) and GetExitCodeThread(FManagerThread.HandlethreadExitCode) and (threadExitCode STILL_ACTIVEthen

Такое решение не выглядит грамотным. Я бы предпочел либо иметь возможность остановить поток вручную, либо останавливать его в ADManager.Close. Во втором случае это можно делать по условной компиляции, т.к. такое поведение, очевидно, нормальным проектам не свойственно.

Пока. АК
Re:inproc COM-сервер и AnyDAC
Posted: 2007/03/30 02:03
 
Привет.

Нельзя ли рассмотреть мою просьбу?

Следует ли мне ждать модификации компонентов или рассчитывать на свои силы?

Пока. АК
[1 2 |Next ]