![]() |
Prozess trotz (mehrfacher) Exceptions fertig abarbeiten
Manchmal möchte man etwas trotz Fehler/Exceptions fertig durcharbeiten lassen...
Nun gibt es da mehere Wege: [*] der böse Weg = einfach den/die Fehler ignorieren ich glaub hier sind wir und einige, daß man sowas nicht macht.
Delphi-Quellcode:
Stand selber grad vor diesem Problem, denn in einer Schleife müssen unbedingt alle Werte abgearbeitet werden,
var
i: Integer; begin for i := 1 to 5 do try // ... except end; aber dennoch sollte die Exception nicht verschwinden. Da es sich hier nur um ein Zusatzmodul (himXML :angel2: ) handelt und im aufrufenden Code eine etwaige Exception dennoch ankommen soll/muß, ist schonmal klar, daß der "böse Weg" absolut nicht in Frage kommt. Ich war schon kurz davor hier zu fragen, was andere da machen würden, aber wärend ich den Beitrag schrieb, da fiehl mir grade noch so ein Tipp ein, welchen mir her jemand vor 'ner Weile mal gegeben hatte ... ![]() [*] also würde man es sich merken, ob eine Exception auftrat und diese später behandeln nur blöde, daß hier keine mehr weiß, was mal war
Delphi-Quellcode:
[*] also noch mehr merken
var
i: Integer; Fehler: Boolean; begin Fehler := False; for i := 1 to 5 do try // ... except Fehler := True; end; if Fehler Then Raise Exception.Create('Irgendein Fehler ist aufgetreten, ' + 'aber ich weiß nicht mehr welcher ._.'); hier hätten wir zwar den Text, aber für eine weitere Fehlerbehandlung ist nun die ursprüngliche Exception selber futsch :(
Delphi-Quellcode:
[*] warum dann nicht gleich alles merken?
var
i: Integer; Fehler: String; begin Fehler := ''; for i := 1 to 5 do try // ... except on e: Exception do Fehler := e.Message; end; if Fehler <> '' Then Raise Exception.Create(Fehler);
Delphi-Quellcode:
Hier wäre es dann so, wie gewollt.
var
SavedExcept: Exception; i: Integer; begin SavedExcept := nil; try for i := 1 to 5 do try // ... except if not Assigned(SavedExcept) then SavedExcept := AcquireExceptionObject; end; finally if Assigned(SavedExcept) then raise SavedExcept; end; end; Die komplette Exception bleibt erhalten, also samt Message und Exception-Klasse. :thumb: hier nochmal ein Beispiel
Delphi-Quellcode:
Nach außen hin wäre es so, als wenn die Prozedur im 2. Durchgang abgebrochen wäre
procedure Test;
var SavedExcept: Exception; i: Integer; begin SavedExcept := nil; try for i := 1 to 5 do try // ... if i in [2..4] then raise Exception.CreateFmt('Durchlauf %d', [i]); // ... except if not Assigned(SavedExcept) then SavedExcept := AcquireExceptionObject; end; finally if Assigned(SavedExcept) then raise SavedExcept; end; end; und man erhält auch die (erste) Exception davon. Dennoch wurde aber die Schleife noch komplett abgearbeitet. [*] und, entsprechend eines Vorschlages, noch die "Extremvariante" hier wird eine Liste aller Exceptions gespeichert und nicht nur die Erste, so wie in den vorhergehenden Beispielen.
Delphi-Quellcode:
verwendet wird es z.B. so
type
EMultiException = class(Exception) protected FList: Array of Exception; function GetCount: Integer; function GetExcept(i: Integer): Exception; public constructor Create(E: Exception); destructor Destroy; override; class procedure AddLastException(var SavedExcept: Exception); class procedure Reraise(SavedExcept: Exception); property SubExceptCount: Integer read GetCount; property SubException[i: Integer]: Exception read GetExcept; end; function EMultiException.GetCount: Integer; begin Result := Length(FList); end; function EMultiException.GetExcept(i: Integer): Exception; begin if (i >= 0) and (i < Length(FList)) then Result := FList[i] else Result := nil; end; constructor EMultiException.Create(E: Exception); begin SetLength(FList, 1); FList[0] := E; Message := FList[0].Message; HelpContext := FList[0].HelpContext; end; destructor EMultiException.Destroy; var i: Integer; begin for i := 0 to High(FList) do FList[i].Free; inherited; end; class procedure EMultiException.AddLastException(var SavedExcept: Exception); begin if not Assigned(SavedExcept) Then SavedExcept := AcquireExceptionObject else if not (SavedExcept is EMultiException) then begin SavedExcept := EMultiException.Create(SavedExcept); EMultiException.AddLastException(SavedExcept); end else with EMultiException(SavedExcept) do begin SetLength(FList, Length(FList) + 1); FList[High(FList)] := AcquireExceptionObject; end; end; class procedure EMultiException.Reraise(SavedExcept: Exception); begin if Assigned(SavedExcept) then raise SavedExcept; end;
Delphi-Quellcode:
und noch ein kleines Beispiel:
var
SavedExcept: Exception; i2: Integer; begin SavedExcept := nil; try for i2 := 1 to i do try // ... except EMultiException.AddLastException(SavedExcept); end; finally EMultiException.Reraise(SavedExcept); end; end;
Delphi-Quellcode:
procedure Test(i: Integer);
var SavedExcept: Exception; i2: Integer; begin SavedExcept := nil; try for i2 := 1 to i do try // ... raise EExternalException.CreateFmt('Test %d', [i2]); // ... except EMultiException.AddLastException(SavedExcept); end; finally EMultiException.Reraise(SavedExcept); end; end; procedure TForm1.FormCreate(Sender: TObject); var i: Integer; S: String; begin try Test(1); except on E: Exception do ShowMessage(Format('%s: "%s"', [E.ClassName, E.Message])); end; try Test(3); except on E: EMultiException do begin S := Format('%s: "%s"'#13#10'*********************', [E.ClassName, E.Message]); for i := 0 to E.SubExceptCount - 1 do S := Format('%s'#13#10'%s: "%s"', [S, E.SubException[i].ClassName, E.SubException[i].Message]); ShowMessage(S); end; on E: Exception do ShowMessage(Format('%s: "%s"', [E.ClassName, E.Message])); end; end; Zitat:
|
Re: Prozess trotz (mehrfacher) Exceptions fertig abarbeiten
Als nächsten Schritt würde ich die Exceptions dann in eine Queue schreiben, damit auch wirklich keine verloren geht.
|
Re: Prozess trotz (mehrfacher) Exceptions fertig abarbeiten
Gut, daß mit der Queue war für mich nicht nötig, da diese Exceptionbehandlung nach Außen nicht sichtbar ist und es dort nur die "normalen" Einzelexceptions gibt ... drum reicht es, wenn die erste Exception rausgereicht wird.
|
Re: Prozess trotz (mehrfacher) Exceptions fertig abarbeiten
So ähnlich wie "Save Exceptions" in einer ForAll-Schleife bei PL/SQL. Nur da kann man am Ende auf alle Exceptions zugreifen.
|
Re: Prozess trotz (mehrfacher) Exceptions fertig abarbeiten
Für Uwe wurde noch 'ne weitere Version angehängt. :angel:
|
Re: Prozess trotz (mehrfacher) Exceptions fertig abarbeiten
Zitat:
|
Re: Prozess trotz (mehrfacher) Exceptions fertig abarbeiten
Ich würde das ganze in eine Funktion auslagern welche keine Exception wirft sondern einen Fehlercode zurück gibt. Wenn verschiedene Fehler aufgetreten sind können mehrere Bits gesetzt werden.
Ich bin der Meinung: Wenn eine Funktion mehrere Aufgaben zusammenfasst soll sie mir auch nicht alles im einzelnen zurück geben sondern auch Fehler etc. entsprechend zusammenfassen bzw. selbständig behandeln. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:41 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-2025 by Thomas Breitkreuz