| Autor |
Beitrag |
Krischa
      
Beiträge: 118
Windows 7 64 Bit
Delphi 2007
|
Verfasst: Di 09.06.09 09:39
Hi,
ich starte mit einem Button-Click eine Ansammlung von Datenbankabfragen. Ich überprüfe bei jeder Abfrage ob das Feld das er ausliest leer ist.
Delphi-Quelltext 1:
| if query1.fieldbyname('Name')<>NULL then ... |
Wenn das Feld jetzt leer ist gibt er mir eine MessageBox aus in welcher Datenbank der Wert fehlt. Nach der MessageBox soll er nun den Programmcode nicht weiter abarbeiten und in den Ausgangszustand zurück gehen (vor dem Drücken des Buttons). Wie kann ich das machen?
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 09.06.09 09:45
Dafür musst du den Zustand vorher speichern. Es gibt nicht irgendwie eine "Undo"-Funktion oder sowas. Wie auch?
|
|
oki
      
Beiträge: 40
Win XP
Delphi 2007 Prof
|
Verfasst: Di 09.06.09 09:48
Am Besten alles, was du bis dahin gemacht hast zurücksetzen. Ich schreib mir dafür immer eine Methode die im Namen was mit "Default" hat. Zum Start des Programms gibt es ja eigentlich ein Sammelsurium von Einstellungen für Buttons, Datenbankzustand usw. Die setze ich dann explizit.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| procedure SetDefaultItems; begin MyButton.Enabled := True; if MyTable1.Open then MyTable1.Close; ... end; |
Diese Methode rufst du dann auf und alle ist wie vorher.
Manno eh, jaenicke war schneller
Gruß oki
_________________ 42
|
|
Krischa 
      
Beiträge: 118
Windows 7 64 Bit
Delphi 2007
|
Verfasst: Di 09.06.09 09:49
Mir würde schon reichen wie ich ihn dazu kriege das Programm anzuhalten und nicht weiter durch zu laufen.
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 09.06.09 09:50
Suchst du vielleicht Exit? Das springt aus der aktuellen Prozedur raus.
|
|
Krischa 
      
Beiträge: 118
Windows 7 64 Bit
Delphi 2007
|
Verfasst: Di 09.06.09 09:54
Ja, das Exit reicht mir.
[Edit]Habe gerade festgestellt exti reicht doch nicht. Es beendet ja nur die aktuelle Funtkion. Aber da ich zwischen mehreren Funktion springe soll er alle beenden. [/Edit]
|
|
glotzer
      
Beiträge: 393
Erhaltene Danke: 49
Win 7
Lazarus
|
Verfasst: Di 09.06.09 11:43
[ironi] wie wärs mit Application.Terminate ? [/ironi]
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 09.06.09 11:44
Dann löse eine Exception aus und fange die in der obersten Ebene mit try..except ab, die nicht mehr abgebrochen werden soll. Delphi-Quelltext 1:
| raise Exception.Create('Oooops'); | Am besten mit einer eigenen Exceptionklasse mit weiteren Details.
|
|
zuma
      
Beiträge: 660
Erhaltene Danke: 21
Win XP, Win7, Win 8
D7 Enterprise, Delphi XE, Interbase (5 - XE)
|
Verfasst: Di 09.06.09 12:15
Wie wäre es, wenn du dir alle Prüfungen in einer Stringlist merkst (Name/Value-Eigenschaften nutzen ala Feld=Wert), somit kannst du durchlaufen lassen, am Ende dann die Liste durchlaufen, die Values prüfen und evtl. alle leeren Felder auf einmal anzeigen.
in etwa so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| if not query1.fieldbyname('Name') <> NULL then lFehlerListe.Add('Name='+query1.fieldbyname('Name').AsString); ...
s := ''; for i := 0 to lFehlerliste.count -1 do if lFehlerliste.ValueFromIndex[i] = '' then s := s + lFehlerliste.Names[i] + 'ist leer'+#13+#10; if s <>'' then showmessage(s); ... |
Stelle mir vor, das das u.U. bequemer ist, als 'nach und nach' rauszufinden, wo noch ein Feldwert fehlt ...
Gehts dir allerdings bei deinem Abbruch um Performance, so hilft dir mein Lösungsansatz leider nicht.
_________________ Ich habe nichts gegen Fremde. Aber diese Fremden sind nicht von hier! (Methusalix)
Warum sich Sorgen ums Leben machen? Keiner überlebts!
|
|
Krischa 
      
Beiträge: 118
Windows 7 64 Bit
Delphi 2007
|
Verfasst: Mi 10.06.09 08:38
Mit dem Exception auslösen hat es prima funktioniert. Wusste garnicht das man die von Hand auslösen kann.
@glotzer deine "ironi" kannst du dir sparen. Ich wollte nicht das ganze Programm beenden sondern nur die Buttonklick-Routine mit all ihren Unterfunktionen
Danke für eure Hilfe
|
|
oki
      
Beiträge: 40
Win XP
Delphi 2007 Prof
|
Verfasst: Mi 10.06.09 09:02
Soory, aber ich halte die Benutzung einer Exzeption für einen regulären Abbruch einer Funktion nicht unbedingt für elegant. Nun kann man sicher über das Thema "Elegant" trefflich streiten, aber ich sehe den Einsatz von Exception als ein Mittel um auf Fehler und Ausnahmeereignisse zu reagieren. In 99% der Fälle wird das auch so sein. Der eine Fall für einen ordnungsgemäßen Abbruch des Ablaufes dann von einem echten Fehler zu unterscheiden ist im Zweifelsfall eher problematisch. Dann doch einfach Exit. Das bewirkt das gleiche, die Funktion wird beendet ohne weiteren Code der Funktion abzuarbeiten. Will man das auch in etwaigen Schleifen tun, so kann man sich eine "globale" Break-Variable anlegen, die bei Click auf einen Abbrechen-Button auf True gesetzt wird. In den entsprechenden Schleifen implementiert man ein Application.ProcessMessages und prüft die Variabel. Ist sie True, dann Exit. Das kann man auch in jede Subroutine implementieren.
Am Ende der Hauptprocedure die abgearbeitet wird setzt man die Variable wieder auf False. Um das auch bei einem Exit hinzubekommen kann man den gesamten Code der procedure in einen try finally Block kapseln. Glücklicherweise wird bei einem Exit nämlich der Code im finally Abschnitt immer ausgeführt.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| var FUserBreak : Boolean; .... procedure DoIt; var Counter : Integer; begin try for Counter := 0 to 100000 do begin Application.ProcessMessages; if FUserBreak then Exit; end; ...... finally if FUserBreak then begin FUserBreak := False; SetDefault; end; end; end;
FUserBreak := True; |
Gruß oki
_________________ 42
|
|
Krischa 
      
Beiträge: 118
Windows 7 64 Bit
Delphi 2007
|
Verfasst: Mi 10.06.09 09:06
Mein Problem mit Exit; ist aber das es nur die aktuelle Funktion beendet. Wenn aber diese durch eine andere gestartet wird, wird die aufrufende Funktion zu ende bearbeitet und das soll sie bei mir nicht.
|
|
oki
      
Beiträge: 40
Win XP
Delphi 2007 Prof
|
Verfasst: Mi 10.06.09 09:12
Dann implementiere die Subfunktionen als Funktionen mit Boolean als Rückgabewert. Frage auch in diesen Procedure an geeigneter Stelle (muss ja nicht hinter jeder CodeZeile sein, reicht oft am Ende) FUserBrake ab oder setze einfach Result := not FUserBrake. Gibt die Funktion False zurück machst du das Exit. Das kann dann auch wieder in den try finally, der dann wiederum Result auf not FUserbraek setzt. So kannst du endlos verschachteln. Die Funktionsaufrufe müssen dann natürlich ausgewertet werden.
Das ist dann sicher auch nicht immer die elegante Lösung. Kommt auf den Code an. Musst du aber eine echte Exception mit einem try except Block behandeln und willst dann nicht abbrechen bekommst du ein Problem mit deiner Abbruchexception, so sie sich im gleichen Block befindet.
Gruß oki
_________________ 42
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 10.06.09 09:27
Deshalb meinte ich ja, am besten wäre eine eigene Exceptionklasse, damit man den Typ der Ausnahme feststellen kann in except. Nämlich, ob der eigene Fehler oder ein anderer aufgetreten ist.
Prinzipiell ist eine Exception durchaus für den Zweck gut geeignet, denn eine Exception soll genau einen solchen Fehler signalisieren. Und anders als mit einem boolschen Wert kann man auch Details dazu in einer eigenen Exceptionklasse mitliefern. Man muss das allerdings auch sauber umsetzen um keine Speicherlecks zu hinterlassen.
|
|
oki
      
Beiträge: 40
Win XP
Delphi 2007 Prof
|
Verfasst: Mi 10.06.09 10:00
Hi jaenicke,
klar ist das ein gangbarer Weg. Ich denke, hier gilt wieder die alte Regel, viele Wege führen nach Rom. Welcher nun der geeignetere ist liegt sicher am Aufbau des konkreten Projektes sowie des Geschmacks des Programmierers. Meine Abneigung eine Exception zu verwenden tendiert definitiv zur Geschmacksecke. Meine Variante hat natürlich auch ihre Nachteile. Will ich Funktionen mit Rückgabewerten verwenden, dann ist Result auch schon "verbraucht". Die dann als var-Parameter zurückzuliefern ist auch nicht das gelbe vom Ei. Man muss also immer schauen was sinnvoll ist. Eigentlich wollte ich nur einen anderen Weg vorstellen und nicht gegen die eigene Exception intervenieren.
Gruß oki
_________________ 42
|
|