![]() |
Exception-Behandlung weiterreichen
Also, da ich ja nun mein himXML nochmal in großen Teilen grundlegend überarbeite, bin ich nun auch an der Exception-Behandlung dran ...
Mein Problem ist nun das Abfangen externer Exceptions, welche mit meinen Programmteilen selber nix zu tun haben. Worauf ich auch absolut keinen Einfluß hab, welches aber dein eigenen Programmablauf eigenlich nicht stören soll. Die eigenen Exceptions werden ja notfalls behandelt und meißtens mit Abruch meiner Rutienen nach außen weitergegeben. Nun soll aber bei den erwähnten Exceptions nichts abbrechen, aber es soll dennoch der Mechianismuß ausgelößt werden, wie wenn eine Exception bis zur "Basis" durchwandert. In den altuell gestellten Sourcens sieht es ja noch so aus:
Delphi-Quellcode:
Da nun aber die Verwendung von ExceptObject und ExceptAddr, bei eventuell vorhandenen MultiThread-Anwendungen, im Grunde ganz böse sein seins sollen, hatte ich es kurzzeitig so.
Procedure TXMLFile.DoNodeChange(Node: TXMLNode; CType: TXMLNodeChangeType);
Begin _Changed := True; If Assigned(_OnNodeChange) Then Try _OnNodeChange(Node, CType); Except ShowException(ExceptObject, ExceptAddr); End; End;
Delphi-Quellcode:
Aber nun ist ShowMessage ja auch nicht das Wahre,
Procedure TXMLFile.DoNodeChange(Node: TXMLNode; CType: TXMLNodeChangeType);
Begin _Changed := True; If Assigned(_OnNodeChange) Then Try _OnNodeChange(Node, CType); Except On E: Exception do ShowException(E, nil); End; End; denn was ist, wenn jemand global die Exceptions nicht anzeigt, sondern z.B. mitloggt? OK, nun ging der Weg also da hin:
Delphi-Quellcode:
Dieses sieht ja nun erstmal garnicht soooo schlecht aus, aber nur wenn man nicht genauer hinguckt.
Procedure TXMLFile.DoNodeChange(Node: TXMLNode; CType: TXMLNodeChangeType);
Begin _Changed := True; If Assigned(_OnNodeChange) Then Try _OnNodeChange(Node, CType); Except If Assigned(ApplicationHandleException) Then {Classes.}ApplicationHandleException(E) Else If Assigned(ApplicationShowException) Then {Classes.}ApplicationShowException(E) Else {SysUtils.}ShowException(E, nil); End; End; Also beim eintreten einer Exception wird z.B. ApplicationHandleException aufgerufen, dort meldet sich z.B. TApplication an und hat da {T}Application.HandleException angemeldet, welches wiederum {T}Application.OnHandleException aufruft, wo man ja wiederrum was Eigenes eintragen kann. Aber beim genauen Hingucken, da mich dieses Sender etwas störte/irritierte,
Delphi-Quellcode:
stieß ich doch wieder auf dieses "böse" ExceptObject :shock:
var
ApplicationHandleException: procedure (Sender: TObject) of object = nil;
Delphi-Quellcode:
Ja und nun meine Frage, wie wüdet ihr das machen?
procedure TApplication.HandleException(Sender: TObject);
var O: TObject; begin if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0); O := ExceptObject;
PS: ShowMessage macht nix Anderes als dieses (funktionelle Kurzfassung von SysUtils.ShowException)
Delphi-Quellcode:
procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer);
begin if IsConsole then WriteLn(ExceptObject.Message) else ShowMessage(ExceptObject.Message); end; |
Re: Exception-Behandlung weiterreichen
Führe doch einfach eine Property ein, ob die Exceptions angezeigt werden sollen und einen Handler OnError oder so.
Dann kannst du genau wie bei deinem Beispiel schauen, ob der Handler zugewiesen ist und den ggf. aufrufen und je nach Einstellung die Meldung anzeigen oder nicht. Wenn der Benutzer dann keine Meldung eingestellt hat und keinen Handler zugewiesen hat, bekommt er eben nix von der Exception mit. Und bei vom Benutzer aufgerufenen Methoden könnte noch eine zusätzliche Property dazukommen, ob die Exceptions mit raise durchgeleitet oder abgefangen und nur ggf. an OnError oder so weitergeleitet werden sollen. So könnte man das genau an die eigene Anwendung und deren Fehlerbehandlung anpassen, denn da unterscheiden sich die Konzepte ja relativ stark. |
Re: Exception-Behandlung weiterreichen
Meine Überlegung war halt, die Exception an die eventuell bereits reistrierte Exception-Behandlung weiterzureichen, so daß eben nicht nocheine weiter Registrierungsstelle dazukommt.
Es geht hier ja nur um Exceptions in den anderen (aktuell noch) zwei StatusEvents, wo die dort eventuell auftetenden Exceptions ja den weiteren Programmablauf nicht verändern (gibt da ja keine Rückkopplung oder so). Also würde ich dann sowas einbauen
Delphi-Quellcode:
ShowError wäre per Standard False und wenn man es auf True setze, würde die Exception-Meldung von mir angezeigt.
type TXMLExceptionEvent = Procedure(E: Exception; Owner: TObject; Var ShowError: Boolean) of Object;
property OnException: TXMLExceptionEvent; Owner wäre dann das Objekt in dessen Ereignisprozedur es passiert ist. |
Re: Exception-Behandlung weiterreichen
ExceptObject und ExceptAddr sind nicht böse. Sie sind Thread-lokal.
|
Re: Exception-Behandlung weiterreichen
Zitat:
Delphi-Quellcode:
type TXMLExceptionEvent = Procedure(Sender: TObject; E: Exception; Var ShowError: Boolean) of Object;
|
Re: Exception-Behandlung weiterreichen
Zitat:
Zitat:
Dachte erst nur, das sei etwas schlecht, da einige Exceptions nicht in der Klasse, sondern in eigenständigen Prozeduren oder Class-Prozeduren auftreten können und es dann keinen Sender gäbe, aber da hatte ich nicht weiter gedacht, da die betreffenden Exceptions ja immer in einer Klasse auftreten müssen, denn sonst gibt es die Ereignisprozeduren nicht, wo die Fehler auftreten könnten :stupid: |
Re: Exception-Behandlung weiterreichen
Wenn ich in meinem Turbo-Delphi in System.pas nachschaue, sehe ich, dass ExceptObject auf RaiseListPtr zurückgreift, welches als threadvar deklariert ist.
|
Re: Exception-Behandlung weiterreichen
Die Variable ist auch als threadvar, nicht als var deklariert, ich weiß aber nicht seit welcher Delphiversion es das gibt und genutzt wird.
Wenn jetzt aber eine weitere Exception auftritt, dann enthält ExceptObject diese neue Exception und die alte ist verloren. |
Re: Exception-Behandlung weiterreichen
Ich finde, Du machst Dir zu viele Gedanken um dieses 'Problem'.
Wenn ein vom Anwender zu implementierendes Event von ihm nicht entsprechend abgesichert ist, dann ist das sein Problem. Ich erwarte als Anwender, das die Klasse ihre Arbeit dann verweigert. Wenn er (der Anwender) sich nicht an die Konvention hält, die Fehler, die dort geschehen, entsprechend zu behandeln, dann *kann* deine Klasse doch nicht einfach weitermachen. Du implizierst dann einen stabilen Systemzustand, der nicht unbedingt gegeben ist. Wohlgemerkt: Die Exception ist unerwartet. |
Re: Exception-Behandlung weiterreichen
Zitat:
Ich hab ja nun meine eigenes Exception-Klasse so weit überarbeitet, so daß z.B. bei einem Re-Raise die vorhergehenden Fehlermeldungen mit übernommen werden, außerdem wird auch außerhalb der IDE der Klassenname der Exception und andere Informationen mit angezeigt. So kann ich die eigentlichen Fehlermeldungen recht kurz/einfach halten und es ist später dennoch erkennbar, wo die Exception nun eigentlich her kommt. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:52 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz