Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Abbrechen und auf Abbruch warten? (https://www.delphipraxis.net/81496-abbrechen-und-auf-abbruch-warten.html)

Mattze 28. Nov 2006 10:43


Abbrechen und auf Abbruch warten?
 
Hallo,

ich schaffe es nicht, eine Schleife extern abzubrechen und auf den erledigten Abbruch zu warten.
Bisher habe ich das so gemacht (nur das Nötige):
Formular mit zwei Schaltern.
Der eine läßte die Schleife los, der andere hält sie an.
Der Implementations-Teil:

Delphi-Quellcode:
var Abbruch: Boolean = False;
    abgebrochen: Boolean = false;

procedure TForm1.Button1Click(Sender: TObject);
begin
    abbruch:=false;
    while true do begin
      application.processmessages;
      if Abbruch then begin
        abgebrochen:=true;
        break;
      end;
    end;
    If abbruch then begin
      showmessage(inttostr(integer(abgebrochen))+'Abbruch');
   end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var i: LongInt;
begin
  abgebrochen:=false;
  abbruch:=true;
  application.ProcessMessages;
{Wird ordentlich abgebrochen. Das "showmessage in Button1Click ist nur zum Gucken. Muss nicht sein!
Nun will ich auf den Abbruch warten und das geht nicht. Abgebrochen bleibt false und es wird auch keine Meldung im ersten //Schalter generiert. Nehme ich diese Schleife weg, geht es ordentlich. Hintergrund: Ich benutze
rekursive Funktionen und er soll erst weitermachen, wenn auch wirklich alles beendet wurde.
Man kann übrigens nicht mal mit Systemmenü oder oben rechts das Programm beenden!!!
Es sieht fast so aus, als wenn er Abbruch:=true erst an das restliche Programm sendet, wenn die
zweite Ereignisprocedure verlassen wird! Aber das ist doch Quatsch, oder?
Button2click geht so weiter:}

Delphi-Quellcode:
  while not abgebrochen do begin
    label1.caption:=inttostr(i);
    inc(i);
    application.ProcessMessages;
  end;
end;
Wo mache ich meinen Denklfehler und wie geht es? Hat jemand einen Tipp?

Gruß
Matthias

GeorgPeifer 28. Nov 2006 11:03

Re: Abbrechen und auf Abbruch warten?
 
Hmm.. also auf den ersten Blick kommt mir while true sehr komisch vor..

while variable=true ist glaube ich das was du eigentlich willst.

Davon mal abgesehen mache ich das ohne Break mit

Delphi-Quellcode:
abgebrochen:=FALSE;

repeat
     .
     .
     application.ProcessMessages;
until abgebrochen;
und in dem 2. Button setze ich dann abgebrochen auf TRUE.

Ines 28. Nov 2006 11:24

Re: Abbrechen und auf Abbruch warten?
 
Hallo Georg,

benötigst Du wirklich diese Unmenge von application.processmessages?
Ich glaube beim 2. Button sind die überflüssig.
Delphi-Quellcode:
Button2:
  abgebrochen:=false;
  abbruch:=true;
  application.ProcessMessages;

Button1:
      if Abbruch then begin
        abgebrochen:=true;
        break;
      end;

Button2:
while not abgebrochen do begin
    label1.caption:=inttostr(i);
    inc(i);
    application.ProcessMessages;
  end;
end;
Aus diesem Grund gibt es keine Ausgabe, da abgebrochen in Button1 auf "true" gesetzt wird.
Viele Grüße
Ines

Mattze 28. Nov 2006 11:54

Re: Abbrechen und auf Abbruch warten?
 
Hallo,

vielen Dank für Eure schnellen Antworten. Bloß leider beantworten sie nicht meine Frage.
Ich wollte eigentlich weniger über die Form der Quellen diskutieren (Ich glaube, ich habe geschrieben, dass es nur das Nötige ist!) als über das Prinzip des Abbruchs mit Warten.

Statt "while true.. " kannst Du auch "While Apfel=true..." oder nur "while Apfel..." schreiben, wenn Apfel eine Variable ist und mit true vorbelegt wurde.

Das application.processmessages brauche ich, um zu sichern, dass wirklich zu diesem Zeitpunkt alle Windows-Messages im Programm abgearbeitet werden. Sonst arbeitet er nämlich nicht mal Abbruch:=true ab, wenn er IN der Schleife sitzt!

Aber wie mache ich denn nun den Abbruch mit Warten?

Gruß
Matthias

Mavarik 28. Nov 2006 12:01

Re: Abbrechen und auf Abbruch warten?
 
Zitat:

Zitat von Mattze

Aber wie mache ich denn nun den Abbruch mit Warten?

Für eine Analyse ist der Sourcecode zu unvollständig...
Unabhängig davon wie man es besser machen könnte... Ich würde sagen, das problem liegt nicht in den Codestellen, die Du "uns" gepostet hast.

Frank :coder:

Mattze 28. Nov 2006 13:24

Re: Abbrechen und auf Abbruch warten?
 
Hallo Frank,

entschuldige, aber ich dachte doch tatsächlich, dass zu einer schriftlichen Nachricht auch ein "Hallo" oder so gehört...

Das, was ich Euch geschickt habe, ist gaaaanz genau das Problem.
Wie geschrieben:
Ein Formular mit zwei Schaltern (und einem Label, um zu sehen, ob abgebrochen irgendwann gesetzt wird - wird es nicht, wenn man es in der zweiten Schleife abfragt!) und die entsprechenden Ereignisprozeduren so, wie aufgeschrieben.
Da das Original nicht wollte, habe ich es auf dieses einfache Programm reduzieret - und siehe da, die gleichen Fehler!

Ich könnte mir aber auch vorstellen, dass es für "Abbruch und warten bis abgebrochen" ein fertiges Prinzip gibt. Es muss doch irgendwie zu machen sein...

(Gut, man könnte die Schleife in einen Thread auslagern und nach dem Abbruch warten, bis der Thread beendet oder angehalten wurde. Das würde evtl. (?) funktionieren. Aber, muss man wirklich gleich mit Kanonen auf Spatzen schießen?)

Gruß
Matthias

Mavarik 29. Nov 2006 07:19

Re: Abbrechen und auf Abbruch warten?
 
HALLO!

Also in der 2. Schleife bleibt der Programm hängen, weil es keine MSG mehr zu behandeln gibt.

Du bist zwar mit dem 1. Application.Processmessages aus der Button1. Schleife rausgesprungen,
aber Du kommst nicht zurück, bis der Button2 event abgearbeitet ist.

Nimm also die Schleife aus dem 2. Button event und schon geht es... Es gibt auch nix zu warten, den nach einem Klick,
wird die 1. Schleife sofort beendet.

Frank :coder:

Mattze 29. Nov 2006 10:35

Re: Abbrechen und auf Abbruch warten?
 
Hallo Frank,

vielen Dank für Deine Antwort.
Das ergibt Sinn, aber warum steht für die Schleife im Button2 keine MSG mehr bereit?
Sprich: In Button1click wird mit abgebroche:=true eine MSG generiert. In Button2 ist er in der 2. Schleife und soll nun "schleifen", bis diese MSG generiert ist. Warum klappt das nicht?
Wenn ich nach dem schnellen Abbruch abgebrochen in Button2 (ohne Schleife) überprüfe, dann wurde es gesetzt. In derf Schleife nimmt er aber nicht das Gesetzte, sondern bleibt bei dem ursprünglichen Wert false.
Bei der ersten Schleife in Button1click nimmt er aber Abbruch:=true irgendwann mal an, was ja dann richtig zum Abbruch führt.

Im Originalprogramm (und nicht nur in meinem!) geht es darum, dass in der 1. Schleife (Button1click) einige sehr rechenintensive Dinge erledigt werden. Prktisch kann ma sich das vorstellen, wie große Schleifen in der Schleife.
Wenn ich nun das Abbruchkommando für die 1. Schleife geb, soll (und kann) er erst ordentlich weitermachen, wenn die wirklich (sauber) abgebrochen wurde. Das heißt, dass alle "Unterschleifen" der 1. Schleife ordentlich beendet wurden. Das kann eine Weile dauern.
Also muss ich tatsächlich irgendwie auf die korrekte Beendigung (durch Abbruch) der 1. Schleife warten.
Dazu wollte ich eben eine Variable bei Abbruch der 1. Schleife setzen, die ich dann in der 2. Schleife (Button2click) abwarte.
Also: 1. Schleife breche ich mit Button2 ordentlich ab, indem ich Abbruch:=true setze. Dabei wird in dieser 1. Schleife eine Variable abgebrochen:=true gesetzt.
In der 2. Schleife warte ich und frage diese Variable nur ab.

Fragt sich, warum ich die 1. Schleife so abbrechen kann, aber es in der 2. Schleife ignoriert wird!?

Ich sehe einfach nicht den inhaltlichen Unterschied zwischen dem Abbruch der 1. Schleife und dem Nichtabbruch der 2. Schleife.

Entwerde dürfte er dann gar nicht in die 2. Schleife kommen, weil abgebrochen:=true von Anfang an gilt, oder er wertet das neue Setzen von abgebrochen:=trfue nicht aus. Aber warum nicht?

Gruß
Matthias

Mavarik 29. Nov 2006 12:02

Re: Abbrechen und auf Abbruch warten?
 
Zitat:

Zitat von Mattze
Das ergibt Sinn, aber warum steht für die Schleife im Button2 keine MSG mehr bereit?

Welche den?

Zitat:

Zitat von Mattze
Sprich: In Button1click wird mit abgebroche:=true eine MSG generiert.

Nein, wie kommst Du den darauf?

Das belegen einer Variable erzeugt doch keine MSG

Zitat:

Zitat von Mattze
Wenn ich nach dem schnellen Abbruch abgebrochen in Button2 (ohne Schleife) überprüfe, dann wurde es gesetzt. In derf Schleife nimmt er aber nicht das Gesetzte, sondern bleibt bei dem ursprünglichen Wert false.

Logisch... Den Die Verarbeitung des Button1 geht erst weiter, wenn Du Button2Click verlassen hast!

Zitat:

Zitat von Mattze
Im Originalprogramm (und nicht nur in meinem!) geht es darum, dass in der 1. Schleife (Button1click) einige sehr rechenintensive Dinge erledigt werden. Prktisch kann ma sich das vorstellen, wie große Schleifen in der Schleife.
Wenn ich nun das Abbruchkommando für die 1. Schleife geb, soll (und kann) er erst ordentlich weitermachen, wenn die wirklich (sauber) abgebrochen wurde. Das heißt, dass alle "Unterschleifen" der 1. Schleife ordentlich beendet wurden. Das kann eine Weile dauern.

OK Aber das Hauptprogramm läuft sowieso erst weiter, wenn Du aus Button1Click rauskommst und das ist auch nicht früher oder später...

mfg Frank :coder:

Mattze 29. Nov 2006 15:23

Re: Abbrechen und auf Abbruch warten?
 
Hallo Frank,

vielen Dank für die Antwort. Gab mir wieder einen Tipp, in welche Richtung ich weitersuchen könnte.

Ich habe nun eine private Msg gebastelt und eine entsprechende Behandlungsroutine. In der wird nur abgebrochen:=true gesetzt.

Bei Abbruch:=true wird in Schleife 1 diese Msg abgesetzt (mit sendmessage oder postmessage).
Schleife 2 wird aber trotzdem nicht abgerochen. Der neue Wert von abgebrochen kommt einfach nicht an.
(Auch mal getmessage und peekmessage probiert!)

Ich weiß einfach nicht, was man da noch machen könnte...

Das "riecht" mir schon fast nach einem Bug in Delphi. Aber ich bin schon immer eher der Meinung, dass da was von mir nicht richtig will. Trotzdem: Was tun?

Ich bin mir ganz sicher, dass sowas geht bzw. gehen müsste. Viele Programme machen das! Wahrscheinlich und z. B. auch nero.(?) Wenn man da das Brennen abbricht, dauert das auch erst noch eine Weile, bis alles ordentlich beendet ist und man die Brennseite zu machen kann!

Gruß
Matthias

GeorgPeifer 29. Nov 2006 15:41

Re: Abbrechen und auf Abbruch warten?
 
Zitat:

Zitat von Ines
Hallo Georg,

benötigst Du wirklich diese Unmenge von application.processmessages?
Ich glaube beim 2. Button sind die überflüssig.

Ines

Im Abbruchbutton ist der application.processmessages Befehl auch unnötig und stört sogar. Kann zur Endlos-Schleife werden.

In der Hauptschleife, die unterbrochen werden soll muss er allerdings sein, da sonst die keine anderen Buttons gehandelt werden.


@Matthias
Nochmal zu while TRUE...

While Apfel würde Sinn machen.. While True hingegen ist doch eine Endlos-Schleife, weil True halt immer True ist - oder? ;-)

Was hälst denn Du von While not Abbruch ... ? Nur so als Tip

Mattze 29. Nov 2006 16:09

Re: Abbrechen und auf Abbruch warten?
 
Hallo Gearg,

ganz so einfach ist das leider nicht.
Wenn ich das application.processmessages aus der 2. Schleife rausnehme, wird Label1.caption nicht mehr aktualisiert! (Das geht übrigens IMMER so, nicht nur bei diesem Programm. Man muss das oft explizit angeben, damit Label.caption aktualisiert wird. Wahrscheinlich geht das tatsächlich über eine Windows-Botschaft!) Zur Endlosschleife wird die 2. Schleife übrigens nie. Wie soll das auch gehen?
(Das hieße nämlich, dass man in der ersten Schleife ordentlich, so wie eigentlich erwartet, eine MSG definieren kann, die dann in der 2. ausgewertet wird. Aber genau das wäre doch die Lösung des Problems und das geht eben nicht. Warum?)

Zum Apfel: Das ist ja gerade der Witz! Die erste Schleife soll eine Endlosschleife sein, die nur extern unterbrochen wird.
(Im echten ist sie das natürlich nicht, aber zur Fehlerillustration reicht das hier!)

Gruß
Matthias

Mavarik 29. Nov 2006 16:16

Re: Abbrechen und auf Abbruch warten?
 
Zitat:

Zitat von Mattze
Zum Apfel: Das ist ja gerade der Witz! Die erste Schleife soll eine Endlosschleife sein, die nur extern unterbrochen wird.
(Im echten ist sie das natürlich nicht, aber zur Fehlerillustration reicht das hier!)

Gruß
Matthias

Also nochmal Dein Grundkonzept ist falsch und es handelt sich hier auch nicht um ein Delphi Bug...

Frank

Mattze 29. Nov 2006 17:31

Re: Abbrechen und auf Abbruch warten?
 
Hallo Frank,

ich glaube auch nicht recht daran, dass es ein Delphi-Bug ist.
Das Grundkonzept dürfte aber auf jeden Fall richtig sein.

Oder Du beweist es mir, in dem Du mir ein funktionierendes Beispiel für einen externen Abbruch und das Warten auf den erfolgten Abbruch zeigst!
Solange Du (oder jemand anderes) das nicht können - sprich: mir ein richtiges funktionierendes Grundkonzept vorgeben können - , finde ich es ziemlich gewagt, von einem falschen Grundkonzept zu sprechen.
In diesem Sinne haben ALLE hinreichend komplexen existierenden Programme - Windows eingeschlossen - ein
falsches Grundkonzept.
Es wurde schon vor langer Zeit mathematisch bewiesen, dass es kein hinreichend komplexes Softwaresystem geben kann (!), das völlig fehlerlos ist! Und Fehler? Falsches Grundkonzept! Oder nicht?

Gruß
Matthias

thkerkmann 29. Nov 2006 19:45

Re: Abbrechen und auf Abbruch warten?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Mattze,

das ist ganz sicher kein Delphi Bug.

Das Problem ist, dass die Prozedur die auf die Beendigung des Abbruchs wartet der Arbeitsprozedur keine Chance gibt zu Ende zu laufen. Das ist das Problem der Ereignis-Warteschleife.

Ich habe hier aber für dich eine Lösung, die nicht wesentlich aufwändiger ist - sie arbeitet mit einem Thread....

aber keine Panik. Ich habe einen Mini Thread, der sogar als universell zu benutzende Routine zur Verfügung steht (unit uThreadFrame) und die eigentliche Arbiet bleibt in deinem Mainform. Du darfst nur nicht auf VCL Elemente zugreifen - eventuell geht das sogar, ich habs nicht probiert.

Und so geht's

Delphi-Quellcode:
type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
    Abbruch: boolean;
    abgebrochen: boolean;
    procedure DoTheWork;
    procedure WorkEnde(Sender:TObject);
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation
uses
  uThreadFrame; // <---- hier steckt der Trick

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Abbruch := false;
  abgebrochen := false;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  aThread: tFramingThread;
begin
  // Button 1 startet die Arbeit....

  // Worker Thread initialisieren
  aThread := tFramingThread.Create(true);
  aThread.ThreadBody := DoTheWork; // hier Prozedur zuweisen, die die Arbeit macht
  aThread.FreeOnTerminate := true; // wichtig
  aThread.OnTerminate := WorkEnde; // optional

  // und loslaufen lassen....
  aThread.Resume;

  label1.Caption := 'running';
end;

procedure TForm1.DoTheWork;
begin
  // hier wird gearbeitet.....

  Abbruch := false;
  while true do
  begin

    // Hier code für die Arbeit

    if Abbruch then
    begin
      abgebrochen := true;
      break;
    end;
  end;
end;

procedure TForm1.WorkEnde(Sender: TObject);
begin
  // wird am Ende der Arbeit aufgerufen, kann auch entfallen (siehe oben)
  if Abbruch then
  begin
    showmessage(inttostr(integer(abgebrochen)) + ' Abbruch');
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i: LongInt;
begin
  // der Abbruch Button ....

  abgebrochen := false;
  Abbruch := true;
  while not abgebrochen do
  begin
    sleep(1); // wichtig, damit der Thread zu Ende laufen kann.

    label1.caption := inttostr(i);
    inc(i);
    Application.ProcessMessages;
  end;
end;

end.
Viel Erfolg beim Ausprobieren.

Gruss

Mavarik 30. Nov 2006 08:14

Re: Abbrechen und auf Abbruch warten?
 
Also nochmal...

ein Application.processmessages ist erstmal eigentlich nix anderes als ein Call. Ein Call auf eine Routinen, die Messages abarbeitet.
Diese funktionalität wird dazu verwenden, dass andere Programm oder Programmteile weiterlaufen können, wenn eine "schleife" oder Programm nicht so schnell in die Systemschleife zurückkehren kann.

Also egal was Du machst, mit welchen tricks Du arbeitest und ob Du Messages erzeugst oder was auch immer... Die Procedure läuft erst mit der nächsten Codezeile weiter, wenn das Return aus diesem Call zurückkehrt.

Delphi-Quellcode:
  while true do
    begin
      ...

      application.processmessages -> Call

      ...
    end;
Daher ist Dein Grundkonzept falsch... Kein Bug, Kein Fehler in Windows.. So funktioniert es einfach nicht...
Wenn Du mir Deine Routine gibst, baue ich Sie so um, dass das was Du möchtest funktioniert.


Frank :coder:

Mattze 30. Nov 2006 15:16

Re: Abbrechen und auf Abbruch warten?
 
Hallo thkerkmann,

vielen Dank! Genau das habe ich geahnt und es mir auch so vorgestellt. (Siehe meine Antwort vom 28.11.2006, 14:24, unten)
Aber ich mag es nicht, bei (vermeindlichen) kleinen Problemen gleich mit der ganz großen Keule zu kommen.
(Threads zu basteln sind für mich kein Problem, aber so ist es natürlich besser. Danke!)

Inzwischen habe ich auch etwas weitergespielt und genau das erreicht, was ich eigentlich wollte. Bis jetzt ohne Thread. Ich weiß noch nicht genau, wo eigentlich der inhaltliche Unterschied ist, nur das ich eben eigentlich keine 2. Schleife brauche, um auf den Abbruch zu warten.
Im Prinzip bin ich aber zu ähnlichen Schlüssen gekommen, warum das mit der 2. Schleife nicht funktionieren kann.
Button1click läuft ja so lange, wie die 1. Schleife noch arbeitet und da wirkt die 2. Schleife so, als wenn ich in Button1click auf die Beendigung von Button1click warte. Das geht natürlich in die Hose.
Wirklich sauber (und parallel) geht das eben nur per Thread. Da wird Button1click ordentlich beendet und der Thread rennt trotzdem weiter usw.
Eigentlich wollte ich ein paar Parameter ändern und die 1. Schleife wieder loslaufen lassen. Ich hätte nicht gedacht, dass das möglich ist, aber man kann in Button1click noch mal Button1click aufrufen.
Jedenfalls geht jetzt alles dufte.
Mal sehen, ob ich das ordentlich in die richtige Routine übersetzen kann...

@Frank:
Hallo Frank,

ehrlich gesagt, verstehe ich Dich da nicht. Warum glaubst Du mit "ein paar tausend Zeilen" der richtigen Routine besser zurecht zu kommen als mit der kurzen Version, die genau den Fehler der Routine erzeugt?
Ich danke Dir aber sehr für Dein Hilfsangebot. Wenn ich nicht zurecht komme, komme ich gerne auf Dein Hilfsangebot zurück, aber, wie gesagt, die Routine ist ziemlich groß und hat "recht unangenehme Sachen drin". Z. B. eine rekursive Funktion, die das ganze Dateisystem abgrast, usw.

Gruß
Matthias


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:25 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz