Форум: "Потрепаться";
Текущий архив: 2003.04.14;
Скачать: [xml.tar.bz2];
ВнизСтранные события в деструкторе... Найти похожие ветки
← →
Ihor Osov'yak (2003-03-30 14:48) [0]Я в общем-то сомневался, куда постить это сообщение: или в основную, или в апи - решил в "потрепаться".
Железная логика, так сказать...
А теперь о проблеме...
Сейчас делаю custom bar для IE, в общем то не столь важно что для IE, я думаю проблема не в ней. Для тех,
кто на знаком с этой технологией - а это очень вероятно - ибо тема специфическая - в двух словах о сем деле.
Это есть инпроц сервер, который среди прочего должен поддерживать IDeskBand. В одном из двух методов
этого интерфейса можно создавать свое окошко. В его качестве можно использовать обычную делфийскую форму, но
саздавать ее нужно хитро - через CreateParented, в качестве parent окошка дается тот хендл, что сообщает IE.
Так вот, в чем траблы. Иногда в деструкторе этой делфийской формы происходит исключение. Причем тогда,
когда эта форма в процессе есть последней (это происходит при закрытии IE). Деструктор вызывается только
раз. То есть всякие варианты с повторным вызовом деструктора исключены.
Да - все исследование делается с помощью записи в лог-файл, иешка запускается самостоятельно, то есть
"искажения отладчиком" также исключены.
После долгих занятий этим самым, удалось определить, что в случае возникновения исключений происходит
повторный вызов деструкторов компонентов, лежащих на этой форме. Это удалось обнаружить, перекрыв
BeforeDestruction одного из компонентов, лежащих на форме (с соотв. записью в лог файл).
Еще одно. Если на форму положить фрейм - то такой повторный вызов деструктора фрейма происходит постоянно.
Причем что странно, повторный вызов наблюдается только для фрейма, для контрольного элемента лежащего за
фреймом, такого не происходит. Еще. Вызов деструкторов компонентов, лещащих в фрейме - не происходит:
Вот выдержка из лога:
14:40:58 PID=0005C0 TIEBand: start CloseDW, ID=2threadID=000004D4
14:40:58 PID=0005C0 TIEBand: VisualForm assigned...
14:40:58 PID=0005C0 TFormIEBand.BeforeDestruction start
14:40:58 PID=0005C0 TIEBand: ReestrDestroyVisualForm, ID=2 threadID=000004D4
14:40:58 PID=0005C0 TFormIEBand.BeforeDestruction done
14:40:58 PID=0005C0 TFormIEBand.Destroy entering Это старт деструктора формы
14:40:58 PID=0005C0 TMyButton.BeforeDestruction <==============
14:40:58 PID=0005C0 TMyButton.Destroy <============== Деструктор компоненті, лежащей вне фрейма
14:40:58 PID=0005C0 TFrame1.Destroy
14:40:58 PID=0005C0 TFrame1.Destroy Повторный вызов деструктора фрейма
14:40:58 PID=0005C0 TFormIEBand: Except in destructor ************ !!!!!!!!
14:40:59 PID=0005C0 TFormIEBand.Destroy leaving
14:40:59 PID=0005C0 TIEBand: CloseDW done.., ID=2
У кого какие идеи будут для обьяснения этих странных событий в деструкторе?
← →
Polevi (2003-03-30 16:10) [1]где код деструктора
← →
Ihor Osov'yak (2003-03-30 16:42) [2]Сорри, первым делом текст ексепшена:
15:55:16 PID=000578 TFormIEBand: Except in destructor ***: Invalid pointer operation
Собственно деструктор:
destructor TVisualForm.Destroy;
{$IFDEF OnDebug}
var s:string;
{$ENDIF}
begin
{$IFDEF OnDebug}
WrTmLog(2,ClassName+".Destroy entering");
{$ENDIF}
try
inherited;
except
{$IFDEF OnDebug}
on E:Exception do begin
s:=E.Message;
WrTmLog(2,ClassName+": Except in destructor ***: "+s );
MessageBox(0,pchar(s),"!!!!",MB_OK+MB_ICONERROR);
end;
{$ENDIF}
end;
{$IFDEF OnDebug}
WrTmLog(2,ClassName+".Destroy leaving");
{$ENDIF}
end;
Реально я работаю с наследниками от TVisualForm, деструктор там не перекрывается.
Деструктор контрольного компонента:
destructor TMyButton.Destroy;
begin
{$IFDEF OnDebug}
WrTmLog(2,"TMyButton.Destroy <==============" );
{$ENDIF}
inherited;
end;
Уничтожение формы инициализируется так: (двух выделеных строчек раньше не было, они доданы из-за принцыпа "трасти надо", на ситуацию они не влияют)
function TBaseIEStrip.CloseDW(dwReserved: DWORD): HResult;
//var h:hwnd;
begin
{$IFDEF OnDebug}
WrLog(2,"");
WrTmLog(2,self.ClassName+": start CloseDW, ID="+IntToStr(ID)+
"threadID="+IntToHex(GetCurrentThreadId,8));
{$ENDIF}
//if BandForm <> nil then BandForm.Destroy;
{$IFDEF OnDebug}
if f_VisualForm <> nil then WrTmLog(2,self.ClassName +": VisualForm assigned...");
{$ENDIF}
InputInCriticalPhase;
if assigned(f_VisualForm) then begin
try
f_VisualForm.Hide;
SetParent(f_VisualForm.Handle,0);
f_VisualForm.Free;
//h:=f_VisualForm.Handle;
f_VisualForm := nil;
//SendMessage(h,WM_Close,0,0);
finally
LeaveCriticalPhase;
end;
end;
Result := S_OK;
{$IFDEF OnDebug}
WrTmLog(2,self.ClassName+": CloseDW done.., ID="+IntToStr(ID));
WrLog(2,"");
{$ENDIF}
end;
Да, еще:
procedure TVisualForm.BeforeDestruction;
begin
{$IFDEF OnDebug}
WrTmLog(2,ClassName+".BeforeDestruction start");
{$ENDIF}
if assigned(fIEStrip) then fIEStrip.ReestrDestroyVisualForm;
inherited;
{$IFDEF OnDebug}
WrTmLog(2,ClassName+".BeforeDestruction done");
{$ENDIF}
end;
procedure TBaseIEStrip.ReestrDestroyVisualForm;
begin
{$IFDEF OnDebug}
WrTmLog(2,self.ClassName+": ReestrDestroyVisualForm, ID="+IntToStr(ID)+" "
+"threadID="+IntToHex(GetCurrentThreadId,8));
{$ENDIF}
InputInCriticalPhase;
f_VisualForm := nil;
LeaveCriticalPhase;
end;
InputInCriticalPhase -> EnterCriticalSection,
LeaveCriticalPhase -> LeaveCriticalSection - это тоже из-за "трасти надо", оно здесь лишнее..
WrTmLog написаны с учетом многопоточной работы..
← →
Ihor Osov'yak (2003-03-30 16:50) [3]Да, в TBaseIEStrip.CloseDW есть маленькая логическая ошибка - это когда f_VisualForm = nil.
Недосмотрел - тогда LeaveCriticalPhasе не вызовется. Но это не важно - я на єту траблу еще не нарывался... Но все равно исправлю..
Страницы: 1 вся ветка
Форум: "Потрепаться";
Текущий архив: 2003.04.14;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.008 c