Модераторы: MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как правильно закрыть форму в ActiveX-объекте, непонятно куда копать, в общем. 
:(
    Опции темы
Voxifer
Дата 5.2.2010, 22:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 27.8.2009

Репутация: нет
Всего: нет



Может быть, не сразу смогу внятно объяснить т.к. тема для меня новая и я в боевом режиме изучаю использование интерфейсов. Проблема в следующем: накатал dll, которая поставляет нужный мне интерфейс. В нем осуществляется вызов обычной VCL-формы. В стороннем приложении вызов моего интерфейса производится по CreateObject("bla-bla"). Затем вызов метода интерфейса приводит к созданию формы (немодальной), осуществляющей некоторые действия, и которая может висеть сама по себе. Но проблема в том, что вызывающее приложение может завершиться, пока моя форма присутствует. В этом случае вываливается AV, впрочем, понятно почему. Непонятно, как с этим бороться? т.к. я еще не слишком глубоко постиг механизм всей этой кухни...

P.S. Мой интерфейс - наследник от IDispatch, инкапсулируется классом так:
Код
...
  IControlWindow = interface(IDispatch)
    ['{67642A6A-7E5E-41E2-A2E3-ECF9D03503C0}']
    procedure ShowControlWindow(iType: Integer; iIndex: Integer); safecall;
  end;
  IControlWindowDisp = dispinterface
    ['{67642A6A-7E5E-41E2-A2E3-ECF9D03503C0}']
    procedure ShowControlWindow(iType: Integer; iIndex: Integer); dispid 201;
  end;

 TControlWindow = class(TAutoObject, IControlWindow)
  procedure ShowControlWindow(iType: Integer; iIndex: Integer); safecall;
 end;

Что, где проверить\отловить надо, чтобы уничтожить форму в момент завершения вызывающего приложения?
PM MAIL   Вверх
Voxifer
Дата 8.2.2010, 13:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 27.8.2009

Репутация: нет
Всего: нет



В общем, проблему решил. Не так как хотелось бы, но зато понял, что иначе нельзя. Но тут объявилась другая проблема.
 Вкратце, происходит следующее: внешнее приложение вызывает мой интерфейс, что приводит к созданию формы. Форма порождает дополнительный поток, который уже запускает другой интерфейс вызвавшего форму внешнего приложения и работает с ним, периодически посылая информацию форме на отображение. При освобождении моего интерфейса форма закрывается, в её деструкторе вызывается Terminate для потока и вот тут происходят его зависания (попытки выяснить с помощью MessageBox'ов, где конкретно - привели меня к CoUninitialize). Принудительный TerminateThread помогает частично, форма закрывается, но вызывающее приложение все равно зависает до тех пор, пока я не попытаюсь вызвать его системное меню на панели задач (тогда, видимо, происходит выход из какого-то дедлока). Причем вставка MessageBox'а сразу после команды Terminate почему-то сразу снимает всю проблему - абсолютно все отрабатывает корректно, сколько я ни дергал это окно. Есть подозрение, что я что-то напутал с потоковой моделью COM, но что именно - не знаю. Между потоками интерфейсы не передаю, поэтому маршаллинг тут не использую. (Де)Инициализировать COM пытался где можно и не можно. Надоело тыкаться, как слепому котенку, уже мозг и гугл сломал, может кто подскажет где я налажал? 
 Вот краткие выдержки из моего кода:

Код

...
initialization
  TAutoObjectFactory.Create(ComServer, TControlWindow, Class_ControlWindow,
    ciMultiInstance, tmBoth);  // Последние два параметра менял в разных вариациях
...

  TUptateThread = class(TThread)
  ...
  public
    FEvent:THandle;
  ...
  end;
  TfmWin = class(TForm)
    ...
    FUpdateThread:TUptateThread;
    ...
  end;
...
constructor TUptateThread.Create(...);
begin
 inherited Create(true);
 ...
 FreeOnTerminate:=false;
 FEvent:=CreateEvent(nil, TRUE, FALSE, 'MyCustomEvent');
 Resume;
end;

destructor TUptateThread.Destroy;
begin
  CloseHandle(FEvent);
  inherited;
end;

procedure TUptateThread.Execute;
var
 FApplication:OleVariant;
 ...
 hr:HRESULT;
 WValue,LValue: integer;
begin
  hr:=CoInitializeEx(nil,COINIT_MULTITHREADED);  // Пытался и COINIT_APARTMENTTHREADED

  FApplication := GetActiveOleObject('Интерфейс вызвавшего приложения');
  
  ... // Инициализация внутренних переменных на основе методов FApplication 
  { Place thread code here }
  while not Terminated do
   begin
    // Работа с FApplication 
    ...
    if (Условие) then PostMessage(FMainForm,WM_USER+NNN,WValue,LValue);  // Форма только отображает полученные от потока значения, сама с интерфейсом не взаимодействует
    Sleep(50);
   end;
  ... // Деинициализация внутренних переменных
  FApplication:=Unassigned;
  SetEvent(FEvent);          // Вот тут сигнализирую об окончании потока, потому что ждать сам поток бессмысленно, ибо зависает
  SetErrorInfo(0,nil);         // Где-то слышал звон, что может помочь... нифига...
  if (hr=S_OK)or(hr=S_FALSE) then CoUninitialize;   // Как показало вскрытие - вот тут происходит зависание
end;

constructor TfmWin.Create(AIndex:integer);
begin
 inherited Create(nil);
 FUpdateThread:=TUptateThread.Create(...);
end;

destructor TfmWin.Destroy;
begin
 try
  ResetEvent(FUpdateThread.FEvent);
  FUpdateThread.Terminate;         // Вот после этого поток может зависнуть, а может и нет
  // MessageBox(0,'Удаление потока','Ахтунг!',0); // Раскомментирование этой магической строчки снимает проблему, но само является проблемой.
  if WaitForSingleObject(FUpdateThread.FEvent ,5000)<>WAIT_OBJECT_0 then 
    TerminateThread(FUpdateThread.Handle,0);
  FUpdateThread.Free;
 finally
  FUpdateThread:=nil;
 end;
 inherited;
end;

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: ActiveX/СОМ/CORBA"

Rrader
Girder

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами


  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Delphi
  • Вопросы по SQL и вопросы по базам данных, не связанные с Delphi, задавать здесь

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Rrader, Girder.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: ActiveX/СОМ/CORBA | Следующая тема »


 




[ Время генерации скрипта: 0.0450 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.