2017-10-31 63 views
16

Uprzejmie proszę o poradę dotyczącą następującego problemu, który napotkałem w Delphi z blokiem try/except.Jak wychwycić wyjątek w zdarzeniu TDataModule.OnCreate?

Mam prostą aplikację - jeden MainForm o nazwie fr_MAIN i jeden TDataModule o nazwie DM. DM nie jest automatycznie tworzone, ale jest on tworzony w czasie wykonywania w fr_MAIN „s Button2.OnClick imprezy:

procedure Tfr_MAIN.Button2Click(Sender: TObject); 
begin 
    try 
    DM := TDM.Create(nil); 
    Showmessage('DM started!'); 
    except 
    on E:Exception do 
    begin 
     Showmessage('DM not started!'); 
    end; 
    end; 

DM ma jakiś kod w swoim OnCreate zdarzenia:

procedure TDM.DataModuleCreate(Sender: TObject); 
begin 
    raise Exception.Create('this is error!'); 
    // DM code here ... 
end; 

Problem polega na tym, że kiedy Klikam na Button2, otrzymuję komunikat wyjątku 'this is error!', reszta DM code here nie działa - co jest poprawne! Ale potem również pojawia się komunikat 'DM started!' zamiast komunikatu 'DM not started!'.

Wyjątek zgłoszony przez DM przerywa akcję, ale nie jest przechwytywany w bloku formularza except!

Dlaczego tak jest?

+0

Domyślnie 'TApplication' mówi' TDataModule' aby połknąć wyjątek wywołany przez zdarzenie 'TDataModule.OnCreate' (zobacz odpowiedź Toma na konkretne szczegóły). Aby wykonać to, o co prosisz, powinieneś zastąpić wirtualny konstruktor 'TDataModule.Create()', aby podnieść wyjątek zamiast używać zdarzenia 'TDataModule.OnCreate'. –

Odpowiedz

20

TDataModule ma specjalnej obsługi wyjątków poruszonych w jego OnCreate imprezy.

Wyjątkiem jest obsługiwana tutaj:

procedure TDataModule.DoCreate; 
begin 
    if Assigned(FOnCreate) then 
    try 
    FOnCreate(Self); 
    except 
    if not HandleCreateException then // <-- here 
     raise; 
    end; 
end; 

function TDataModule.HandleCreateException: Boolean; 
begin 
    if Assigned(ApplicationHandleException) then 
    begin 
    ApplicationHandleException(Self); // <-- here 
    Result := True; 
    end 
    else 
    Result := False; 
end; 

Domyślnie TApplication przypisuje TApplication.HandleException() do ApplicationHandleException:

constructor TApplication.Create(AOwner: TComponent); 
var 
    ... 
begin 
    inherited Create(AOwner); 
    ... 
    if not Assigned(System.Classes.ApplicationHandleException) then 
    System.Classes.ApplicationHandleException := HandleException; // <-- here 
    if not Assigned(System.Classes.ApplicationShowException) then 
    System.Classes.ApplicationShowException := ShowException; 
    ... 
end; 

Więc TDataModule.DoCreate() jest łowienie wyjątek i przekazaniem go do TApplication.HandleException(), który następnie wyświetla domyślnie wyskakujące okno dialogowe. I od TDataModule.HandleCreateException() następnie zwraca True, złapany wyjątek nie jest ponownie podniesiony. Wyjątek jest teraz uważany za obsługiwany, co pozwala programowi normalnie kontynuować wywołanie Showmessage('DM started!');.

Aby uniknąć okno wyskakujące, gdy jest wyjątek, można przypisać obsługi zdarzeń: TApplication.OnException

Vcl.Forms.TApplication.OnException

Zastosowanie onException zmienić domyślne zachowanie, które występuje, gdy wyjątek nie jest obsługiwany przez kod aplikacji. Zdarzenie OnException event jest wywoływane automatycznie w metodzie HandleException.

Ale wyjątek nadal będzie przechwytywany i zwalniany przez TDataModule.DoCreate(). Jeśli chcesz tego uniknąć, więc wyjątek propaguje do góry stos wywołań, w żadnym razie nie podnoś wyjątku ze zdarzenia TDataModule.OnCreate. Zastąp wirtualny konstruktor TDataModule.Create() i zamiast tego wywołaj wyjątek.

: To samo dzieje się również w TCustomForm.

+1

Dzięki @Remy za Twoje zmiany. Doskonały. –

+0

Dziękuję bardzo, drogi Panie Lebeau i Panu Brunberg! Tym razem nauczyłem się czegoś bardzo ważnego o tym, jak to się dzieje w przypadku zdarzenia TDataModule Create. Aby rzucić więcej światła na to, w niedalekiej przyszłości DM zostanie utworzony (i zwolniony) z TService - co dla mnie komplikuje rzeczy bardziej. Mam pomysł, który zaprezentowałeś, ale z moimi umiejętnościami na Delphi w tej chwili nie mieszkam w nim - przynajmniej dopóki nie ustanowię TService - na chwilę dostanę się przez fakt, poza wyjątkiem wyjątku Raise Exception.create wewnątrz DM.Create z innej jednostki dziękuję bardzo z pozdrowieniami – altink