Topic: inproc COM-сервер и AnyDAC
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
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...
| заканчивается таймаутом. Судя по монитору все компоненты и модуль уже удалены. Применение из примера использования AnyDAC в dll желаемого результата не принесло. На настоящий момент проблема решена так: в DataModuleDestroy добавлена строка (ADManager as IADPhysManager).Close(True)
|
Насколько это правильно и какие могут быть подводные камни?
С уважением. АК.
|
|
Diman
Admin
 Admin
| Posts: 1509 |  | Karma: 20 |
|
Re:inproc COM-сервер и AnyDAC
|
|
Posted: 2007/03/14 07:46 |
|
|
|
|
Привет
Попробуйте добавить в интерфейс сервера метод ReleaseEngine (или как еще назовете) и в его реализации вызывать ADManager.Close. В свою очередь метод ReleaseEngine сервера вызывайте перед тем, как отсоединиться от сервера.
Удачи, Дмитрий
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
Re:inproc COM-сервер и AnyDAC
|
|
Posted: 2007/03/14 08:33 |
|
|
|
|
Привет.
Примерно так и делаю. В деструкторе СОМ-объекта вызывается деструктор datamodule, в DataModule.OnDestroy вызываю (ADManager as IADPhysManager).Close(True)
| Отличие последнего от состоит в параметрах вызова procedure TADPhysManager.InternalClose(ATerminate, AWaitForClose: Boolean);
|
Если AWaitForClose = True, то натыкаюсь на lTimeOut := WaitForSingleObject(GClosedEvent...
| Т.е. вызова procedure TADPhysManagerThread.SignalClosed;
| не происходит (она вызывается из двух мест: destructor TADPhysManagerThread.Destroy;
| и в procedure TADPhysManagerThread.DoIdle;
| Почему так происхотит, я не разобрался. Это и вызывает беспокойство. Иначе говоря, можно ли вызывать (ADManager as IADPhysManager).Close(True) вместо ADManager.Close ?
PS. Не очень удобно, что письмо с уведомлением об ответе приходит без указания кодировки, хотя, возможно, это проблема почтового клиента.
С уважением. АК
|
|
Diman
Admin
 Admin
| Posts: 1509 |  | Karma: 20 |
|
Re:inproc COM-сервер и AnyDAC
|
|
Posted: 2007/03/14 08:51 |
|
|
|
|
Привет
(ADManager as IADPhysManager).Close(True) вместо ADManager.Close Первое не есть корректно. Используйте ADPhysManager.Close(True). Его вы можете использовать вместо ADManager.Close.
Удачи, Дмитрий
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
Re:inproc COM-сервер и AnyDAC
|
|
Posted: 2007/03/14 08:53 |
|
|
|
|
|
Пардон. ADManager не реализует IADPhysManager. Теперь я не знаю, как вызвать TADPhysManager.InternalClose(True, True); и избежать WaitForSingleObject
|
|
Diman
Admin
 Admin
| Posts: 1509 |  | Karma: 20 |
|
Re:inproc COM-сервер и AnyDAC
|
|
Posted: 2007/03/14 08:55 |
|
|
|
|
|
ADPhysManager.Close
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
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 сервера.
Может быть, есть какие-нибудь гипотезы? Что еще можно проверить?
Пока. АК
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
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
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
Re:inproc COM-сервер и AnyDAC
|
|
Posted: 2007/03/23 03:24 |
|
|
|
|
Привет.
Я немного поспешил с заявлением, что проблема решена. Дело в том, что вызов ADTerminate затрагивает глобальные приватные переменные и является необратимым. Таким образом, его не следует вызывать из деструктора СОМ-объекта, т.к. СОМ-клиент в общем случае, удалив один объект, может создать новый. Теперь напомню суть проблемы - между деструктором последнего СОМ-объекта и отгрузкой сервера (выполнения секций finalization) происходит принудительное удаление всех потоков, в том числе - TADPhysManager.FManagerThread, который на тот момент находится в состоянии ожидания (FMessageEvent.WaitFor(FTimeout)...). Такая ситуация кодом AnyDAC не предусматривается и lTimeOut := WaitForSingleObject(GClosedEvent, C_AD_PhysManagerShutdownTimeout) = WAIT_TIMEOUT;
| в TADPhysManager.InternalClose завершается по таймауту. Сейчас я временно использую такую заплату: там же строку if FManagerThread <> nil then
| расширил так if (FManagerThread <> nil) and GetExitCodeThread(FManagerThread.Handle, threadExitCode) and (threadExitCode = STILL_ACTIVE) then
| Такое решение не выглядит грамотным. Я бы предпочел либо иметь возможность остановить поток вручную, либо останавливать его в ADManager.Close. Во втором случае это можно делать по условной компиляции, т.к. такое поведение, очевидно, нормальным проектам не свойственно.
Пока. АК
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
Re:inproc COM-сервер и AnyDAC
|
|
Posted: 2007/03/30 02:03 |
|
|
|
|
Привет.
Нельзя ли рассмотреть мою просьбу?
Следует ли мне ждать модификации компонентов или рассчитывать на свои силы?
Пока. АК
|
|
|