Autor Beitrag
Krischa
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 118

Windows 7 64 Bit
Delphi 2007
BeitragVerfasst: 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.
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 40

Win XP
Delphi 2007 Prof
BeitragVerfasst: 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.
ausblenden 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 :cry:

Gruß oki

_________________
42
Krischa Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 118

Windows 7 64 Bit
Delphi 2007
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 09.06.09 09:50 
Suchst du vielleicht Exit? Das springt aus der aktuellen Prozedur raus.
Krischa Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 118

Windows 7 64 Bit
Delphi 2007
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 393
Erhaltene Danke: 49

Win 7
Lazarus
BeitragVerfasst: Di 09.06.09 11:43 
[ironi] wie wärs mit Application.Terminate ? [/ironi]
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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.
ausblenden Delphi-Quelltext
1:
raise Exception.Create('Oooops');					
Am besten mit einer eigenen Exceptionklasse mit weiteren Details.
zuma
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 660
Erhaltene Danke: 21

Win XP, Win7, Win 8
D7 Enterprise, Delphi XE, Interbase (5 - XE)
BeitragVerfasst: 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:

ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 118

Windows 7 64 Bit
Delphi 2007
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 40

Win XP
Delphi 2007 Prof
BeitragVerfasst: 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.

ausblenden 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
      // do anything
      Application.ProcessMessages;
      if FUserBreak then
        Exit;
    end;
    // do anything
    ......
  finally
    if FUserBreak then begin
      FUserBreak := False;
      SetDefault;
    end;
  end;
end;

// Ereignisbehandlung für Button-Click Abbrechen
  FUserBreak := True;


Gruß oki

_________________
42
Krischa Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 118

Windows 7 64 Bit
Delphi 2007
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 40

Win XP
Delphi 2007 Prof
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 40

Win XP
Delphi 2007 Prof
BeitragVerfasst: 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