| Autor |
Beitrag |
darksign
      
Beiträge: 58
|
Verfasst: Mi 07.01.09 17:17
Hallo!
Ich habe eine Aufgabe in Delphi 7 zu lösen, und bräuchte nun eure Hilfe, wie man das Ganze angehen soll (ich hab zwar schon eine Lösung, glaub aber, dass es viel einfacher gehen würde):
Ich habe eine For-Schleife mit mehreren Schritten(meistens 5 Schritte). Bei jedem Schritt werden einige Aufgaben durchgeführt (Tabellen befüllen, SQL's absetzen, ...). Es DARF aber erst mit dem nächsten Schritt begonnen werden, wenn ein bestimmtes Ereignis eingetreten ist (es wird in einem Timer zyklisch eine bestimmte Variable in einer Steuerung abgefragt, wenn diese Variable einen bestimmten Wert erreicht hat und der User eine bestimmte Aktion ausgeführt hat, dann darf mit dem nächsten SChritt begonnen werden?).
Wie sollte man nun das Ganze angehen, wie wird die For-SChleife am Besten unterbrochen, solange bis ein bestimmtes Ereignis eintritt (es werden zwischenzeitlich auch noch einige andere Dinge vom Benutzer nacheinander abgearbeitet, erst wenn die letzte Aktion ausgeführt worden ist, darf der Schritt beendet werden und ein neuer begonnen!)
PS: Nur zum Verständis: Ich will die For-Schleife nicht abbrechen, sondern nur solange pausieren, bis die Ereignisse eintreten!
mfg
|
|
DerNetteNachbar
      
Beiträge: 224
|
Verfasst: Mi 07.01.09 17:20
Am besten eine andere Herangehensweise probieren. Denn eine for Schleife wird es schwer sein zu unterbrechen. Wie wärs mit einer while Schleife.
lg
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 07.01.09 17:22
Moin!
darksign hat folgendes geschrieben : | | PS: Nur zum Verständis: Ich will die For-Schleife nicht abbrechen, sondern nur solange pausieren, bis die Ereignisse eintreten! |
Dann hast du einen schweren Bug in deinem Konzept, so arbeitet man nicht ereignisorientiert.  Zum Thema "ereignisorientiert Warten" haben wir auch was in der FAQ.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
darksign 
      
Beiträge: 58
|
Verfasst: Mi 07.01.09 17:34
hmm, und wie soll ich das sonst lösen, hat jemand eine Ahnung?
Im Prinzip geht es um folgendes:
Ich arbeite mit Rezepten, jedes Rezept hat mehrere Zutaten. Von jeder Zutat braucht man eine gewisse Menge (Kilogramm).
Wenn ich nun ein Rezept habe, dann hole ich mir die Einzelnen Zutaten raus, und gehe diese einzeln durch (for 1 to z.B. 5).
Jede Zutat muss auf einer Waage verwogen werden, und erst dann, wenn die Richtige Menge verwogen wurde (diese Verwiegung überprüfe ich zyklisch), dann darf mit der nächsten Zutat weitergearbeitet werden!
Wie könnte ich das sonst lösen?
mfg
|
|
DerNetteNachbar
      
Beiträge: 224
|
Verfasst: Mi 07.01.09 17:44
While Schleife bis das richtige Gewicht erreicht wurde und oberhalb eine For Schleife die die Zutaten zählt.
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 07.01.09 17:46
Du hast eine Liste der Zutaten. Du bist in dieser Liste bei einer bestimmten Zutat, und du weißt welches Zielgewicht du brauchst um die entsprechende Menge dieser Zutat hinzugefügt zu haben.
Mehr brauchst du ja nicht zu einem beliebigen Zeitpunkt. Ein Timer (nehme ich mal an?) prüft bis das richtige Gewicht erreicht ist. Erkennt er, dass es erreicht ist, dann zeigt er das an und geht zur nächsten Zutat über. Der Timer läuft dann erneut bis das Gesamtgewicht erreicht ist, etc.
DerNetteNachbar hat folgendes geschrieben : | | While Schleife bis das richtige Gewicht erreicht wurde und oberhalb eine For Schleife die die Zutaten zählt. |
Das ist genau die falsche Herangehensweise... 
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mi 07.01.09 18:51
Es gibt verschiedene Möglichkeiten. Handelt es sich um ein Konsolenprogramm, kannst du es mit einer For-Schleife, einer inneren while/repeat-Schleife und Sleep lösen. Handelt es sich um ein "Fensterprogramm", hast du drei Möglichkeiten. Entweder mit for-Schleife und darunter eine Schleife mit Application.HandleMessage und Timer; ein separater Thread mit einer for- und einer inneren Schleife und Sleep; oder, eine ereignisorientierte Implementation.
Letzteres würde ich dir empfehlen. Mach z.B. eine Liste von Tasks. Dabei kann TTask eine abstrakte Klasse sein, welche Methoden wie IsTaskCompleted zur Verfügung stellt. Das kann man verschieden lösen...
Im Progrmam hast du dann einen Timer und eine Zählvariable. Im Timer-Ereignis überprüfst du ob der aktuelle Task gemäss Zählvariable erfüllt ist, falls ja erhöhst du den Wert der Zählvariable um 1. So geht das dann durch das ganze Rezept durch. Eigentlich nicht viel anders als bei einer for-Schleife...
Natürlich solltest du noch sicherstellen, dass die Waage wieder leer ist, bevor du zur nächsten Zutat gehst. Sonst gibt es Probleme, wenn du die gleiche Menge mehrerer Zutaten nacheinander wägen musst. Das ist aber ein anderes Problem.
|
|
Dunkel
      
Beiträge: 682
Mac OS X Snow Leopard
Xcode 3.1
|
Verfasst: Mi 07.01.09 18:56
darksign hat folgendes geschrieben : | | Es DARF aber erst mit dem nächsten Schritt begonnen werden, wenn ein bestimmtes Ereignis eingetreten ist... |
Und genau das, was Du schon selber geschrieben hast, ist die eigentlich richtige Herangehensweise: Ereignis-gesteuerte Programmierung.
Z.B. kannst Du dir eine Klassen-Member-Variable (bitte keine globale Variable) definieren, welche mit jedem Eintrit des Ereignises (Gewicht erreicht) um eins inkrementiert wird; das ist dann quasi Deine "Schleifenvariable". Innerhalb dieser Ereignisbehandlung kannst Du dann anhand dieser Variable bestimmen, welche Zutat als nächstes dran ist.
Moderiert von Narses: Zitat entfernt
_________________ Ich streite einsam mich mit dieser Oberflächenwelt
Gutes sei ein löblich Brot von dem ich zehre - bis zum Tod [Das Ich - Im Ich]
|
|
darksign 
      
Beiträge: 58
|
Verfasst: Mi 07.01.09 19:03
äh, irgendwie versteh ich nicht genau, was du meinst, kannst du das eventuell nochmal Idiotensicher erklären?
Ich hätte mir es eventuell so gedacht:
eine Prozedur, welche Überprüft, ob alle Bedingungen erfüllt sind:
Quelltext 1: 2: 3: 4:
| procedure checkSchritt() { //Prüfen, ob alles gemacht wurde (Gewicht erreicht, Benutzeraktionen durchgeführt, ...), wenn ja: Erfüllt=TRUE } |
dann die eigentliche For-Schleife für die Schritte
Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| for 1 to AnzahlSchritte { while ERFÜLLT=false { checkSchritt() } Erfüllt=FALSE } | Kann es so funktionieren, oder wird das dann ne Endlosschleife
Moderiert von Narses: code-Tags hinzugefügt
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mi 07.01.09 19:18
Du musst uns schon sagen was für eine Art von Programm (Konsole/Service/Fensterprogramm) du schreibst und wie es an die Waage gekoppelt ist. Die meisten haben eine ereignisorientierte Lösung vorgeschlagen, dein Pseudocode ist wieder "linear".
|
|
darksign 
      
Beiträge: 58
|
Verfasst: Mi 07.01.09 20:07
es handelt sich um ein Fensterprogramm (GUI)!
Wie könnte in meinem Fall eine ereignisorientierte Lösung aussehen (bitte idiotensicher erklären).
Die Waage wird über TCP/IP angesprochen, aber die ist nicht mein Problem! Damit ich das Gewicht bekomme, muss ich einfach ne Variable auslesen! Ich weiß nur nicht, wie ich durch die einzelnen Schritte soll!
PS: Was ist eigentlich an meiner Lösung mit der Check-Prozedur falsch
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mi 07.01.09 20:33
jaenicke hat folgendes geschrieben : | | Ein Timer (nehme ich mal an?) prüft bis das richtige Gewicht erreicht ist. Erkennt er, dass es erreicht ist, dann zeigt er das an und geht zur nächsten Zutat über. Der Timer läuft dann erneut bis das Gesamtgewicht erreicht ist, etc. |
delfiphan hat folgendes geschrieben : | | Im Progrmam hast du dann einen Timer und eine Zählvariable. Im Timer-Ereignis überprüfst du ob der aktuelle Task gemäss Zählvariable erfüllt ist, falls ja erhöhst du den Wert der Zählvariable um 1. So geht das dann durch das ganze Rezept durch. Eigentlich nicht viel anders als bei einer for-Schleife... |
Dunkel hat folgendes geschrieben : | | Z.B. kannst Du dir eine Klassen-Member-Variable (bitte keine globale Variable) definieren, welche mit jedem Eintrit des Ereignises (Gewicht erreicht) um eins inkrementiert wird; das ist dann quasi Deine "Schleifenvariable". Innerhalb dieser Ereignisbehandlung kannst Du dann anhand dieser Variable bestimmen, welche Zutat als nächstes dran ist. |
Es haben mehrere Leute das gleiche in eigenen Worten erklärt. Was verstehst du denn nicht.
PS: An der Checkprozedur ist wohl nichts falsch (besteht ja nur aus einer Zeile Kommentar), ausser dass es eher eine Funktion sein sollte statt mit einer externen Variable zu arbeiten. Das Problem ist der Rest. Du kannst keine for-Schleife verwenden, da du diese, wie du selbst bereits gemerkt zu haben scheinst, nicht mal eben schnell unterbrechen kannst. Bzw. rein theoretisch ginge es à la ShowModal mit HandleMessage, wie von mir vorgeschlagen (Möglichkeit 1 unter Fensterprogramm), aber nicht zu empfehlen, da schlechter Stil, da Programmausführungspfad spaghettimässig.
|
|
darksign 
      
Beiträge: 58
|
Verfasst: Mi 07.01.09 20:53
naja, es ist ja so das es nicht nur um das Gewicht geht!
Der Ablauf sieht so aus:
1) Rezept wird ausgewählt
2) ein Objekt vom Typ "Rezept" wird erzeugt (dieses enthält die Zutaten samt den Infos dazu, z.B. Zutatenname, Sollgewicht, ...)
3) Als nächstes muss der Benutzer einige Aktionen durchführen (einige Dinge in dem Fensterprogramm auswählen)
4) Erst dann darf das Gewicht verwogen werden
5) Wenn ein bestimmtes Sollgewicht erreicht wird, dann muss noch eine abschließende Aktion vom Benutzer folgen
6) Erst jetzt darf die nächste Zutat durchlaufen werden
Ich versteh nun nicht, wie ich diese ganzen Events, die durchgeführt werden müssen, "bündeln" soll -> erst wenn alle erfüllt sind, darf die nächste Zutat verarbeit werden
meinst du eventuell so:
Eine Membervariable, wo ich die aktuelle Schrittnummer reinspeichere (das halt nur solange, bis die maximale SChrittnummer erreicht ist)
1) Ich beginne mit der ersten SChrittnummer
2) Arbeite diesen Schritt ab, und rufe evenuell laufend eine Check-Prozedur auf, welche überprüft, ob alle Bedinungen zutreffen
3) Fall alle Bedingungen zutreffen, wird die Membervariable um 1 erhöht und der nächste SChritt abgearbeitet
Ich weiß nur nicht, wie ich prüfen soll, ob der Benutzer seine Aktionen schon ausgeführt hat und wann die Gewichtsüberprüfung starten soll! Wie kann ich alle Prüfungen bündeln?
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 07.01.09 21:05
darksign hat folgendes geschrieben : | meinst du eventuell so:
Eine Membervariable, wo ich die aktuelle Schrittnummer reinspeichere (das halt nur solange, bis die maximale SChrittnummer erreicht ist)
[...] |
Ja, genau. darksign hat folgendes geschrieben : | 3) Als nächstes muss der Benutzer einige Aktionen durchführen (einige Dinge in dem Fensterprogramm auswählen)
4) Erst dann darf das Gewicht verwogen werden |
Das könntest du über die Anzeige eines Formulars für die Eingabe der Daten mit ShowModal lösen. Was nach ShowModal kommt wird ja erst danach ausgeführt.
Danach könntest du dann z.B. in deinem Rezeptobjekt eine Eigenschaft auf die erste Zutat setzen und den Timer starten.
Im Timer kann der dann die aktuellen Daten auslesen. Ist das richtige Gewicht erreicht, deaktivierst du den Timer und führst die entsprechenden Aktionen noch im Timerereignis durch.
Wenn das Rezept noch nicht fertig ist, dann setzt du jetzt die Eigenschaft, die das aktuelle Rezept anzeigt auf das nächste. Dafür könnte es z.B. eine Methode in deinem Rezeptobjekt geben, die das macht oder du setzt den Wert selbst.
Danach startest du den Timer wieder.
Die richtig schöne Lösung wären natürlich richtige Threads, aber das wird dann noch komplizierter und ist in diesem Fall wohl gar nicht nötig. 
|
|
darksign 
      
Beiträge: 58
|
Verfasst: Mi 07.01.09 21:34
hmm, es MUSS leider alles in einem Fenster ablaufen, ich kann kein zweites machen!
Aber ich glaub ich weiß schon wie ich es lösen werde:
1) Aktuelle Zutatennummer speichern (in Membervar) und ein Objekt des Rezepts erstellen.
2) Warten auf die Benutzeraktion (wenn der Benutzer nichts macht, dann wird halt ewig gewartet, dass ist nicht mein Problem), wenn die Aktion abgeschlossen ist, wird der Timer für die Gewichtsüberprüfung gestartet!
3) Wenn das Gewicht erreicht ist, werden von mir einige Daten geschrieben, erst dann wird die Zutatennummer erhöht und alles beginnt von vorne
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 07.01.09 21:44
darksign hat folgendes geschrieben : | | hmm, es MUSS leider alles in einem Fenster ablaufen, ich kann kein zweites machen! |
Dann musst du eben das Starten des Timers in die Bestätigung der Benutzereingaben legen.
Du kannst das ganze natürlich auch in eine eigene Klasse auslagern, die dann jeweils die Benachrichtigung bekommt, wenn eine bestimmte Aktion passiert.
Ein Rezept wurde ausgewählt.
Die Oberfläche meldet, dass die Eingaben bestätigt wurden.
Der Timer meldet, dass das Gewicht erreicht ist.
Die Oberfläche meldet, dass die Eingaben bestätigt wurden.
etc.
Darauf kannst du ja jeweils reagieren. Direkt warten (per Schleife) musst du nie, denn Code muss ja nur nach definierten Ereignissen ausgeführt werden.
Die Klasse sorgt dann für die Freischaltung bestimmter Eingabefelder, für das Starten des Timers, etc.
|
|
|