![]() |
Laufende whileschleife auf Knopfdruck unterbrechen
Hallo zusammen,
eigentlich dachte ich es wäre trivial aber dem scheint nicht so.. Folgende Situation: Ich habe eine whileschleife:
Delphi-Quellcode:
An anderer Stelle habe ich
while a=b and c=true
begin .. einige anweisungen bliblablubb .. c=PackageProcess.GetConnectstate end
Delphi-Quellcode:
Jetzt zu meinem Problem:
procedure TForm_WLNConnectionNMEA.Button_DisconnectClick(Sender: TObject);
begin PackageProcess.SetConnectStateFalse; PackageProcess.DisconnectFromHost(Memo,IdTCPClient1); end; Ich kann die whileschleife nicht per Knopfdruck beenden. Der ConnectState wird nicht aktualisiert weil ich überhaupt nicht mehr in die ButtonClick Methode reinkomme sobald die Schleife läuft. Ich brauche also eine Möglichkeit, dass die Knopfdruckmethode höchste Priorität hat und Sofort ausgeführt wird sobald ich den Knopf drücke. Oder gibt es eine bessere Methide? Kann mir jemand helfen? |
AW: Laufende whileschleife auf Knopfdruck unterbrechen
Das ist etwas kompliziert:
Wenn Deine Schleife läuft ist Dein Projekt mit der beschäftigt und kommt nicht dazu, die Formularereignisse abzuhandeln. Wann soll es das auch tun? Wenn Du das willst, musst Du dem Formular extra Rechenzeit zur Verfügung stellen. Das geht am einfachsten mit Application.ProcessMessages z.B. am Ende jeden Schleifendurchlaufs. Das bremst natürlich die Geschwindigkeit des Schleifendurchlaufs aus. Das Projekt muss ja immer zwischendurch die Ereignisse behandeln. Manchmal ruft man das daher auch nur jeden 1000ten Durchlauf auf oder so. Man muss natürlich auch darauf achten, dass man nichts zerstört oder verändert, was in der Schleife benutzt wird. Besser wäre grundsätzlich, für jeden Prozess eigene Threads zu benutzen aber für den Anfang geht auch die Lösung mit ProcessMessages. |
AW: Laufende whileschleife auf Knopfdruck unterbrechen
Vielen dank für die schnelle Reaktion.
Ich hab die Anweisung Application.ProcessMessages bereits in der Schleife. Er liest dann zwar den Status aus aber da der Knopfdruck diesen nicht verändert sondern auf das knopfdrücken garnicht reagiert geht die Schleife direkt weiter. Ich habe schon überlegt zu invertieren, dass ich den Status von c in der Schleife auf false setze und dann eine Art: "derKnopfwurdenichtgedrückt" wieder zuück. Denkbar oder komplett umbauen und mit threads lösen? wie kann ich das für mein Problem nutzen? |
AW: Laufende whileschleife auf Knopfdruck unterbrechen
Die Informationen sind nicht sehr aussagekräftig.
Mein Vorschlag: Bau Dir ein kleines Demoprojekt das nur eine Schleife und einen Button zum starten und zum abbrechen implementiert. So wird es wohl am einfachsten, die Abläufe nachzuvollziehen und zu lernen. Wenn Du das nicht willst, dann schau zumindest mal, ob Dein ButtonClick abgearbeitet wird (Haltepunkt setzen). Du kannst natürlich hier auch mal Dein Projekt als Zip anhängen. Aber ich denke, da wird einiges noch recht suboptimal laufen. ;-) Mit Threads würde ich jetzt an Deiner Stelle noch nicht anfangen. |
AW: Laufende whileschleife auf Knopfdruck unterbrechen
Ich würde es erst mal mit der SuFu versuchen. "schleife unterbrechen" und schon hast du eine Menge Vorschläge :thumb:
|
AW: Laufende whileschleife auf Knopfdruck unterbrechen
Ich nehme das hier:
Code:
Problem ist, dass man die Taste je nachdem, wie viel er in der Schleife macht, etwas länger drücken muss, bis die SChleife halt an dem Teil vorbeikommt.
if GetAsyncKeyState(VK_ESCAPE) < 0 then
Exit; |
AW: Laufende whileschleife auf Knopfdruck unterbrechen
Ich verwende das:
Delphi-Quellcode:
Durch den Aufruf von
Type
TMyForm = class (TForm) Procedure ButtonAbbruchClick(Sender : TObject); ... FSchleifenAbbruchErwuenscht : Boolean; Property SchleifenAbbruchErwuenscht : Boolean Read FSchleifenAbbruchErwuenscht Write SetSchleifenAbbruchErwuenscht; ... Procedure MeineSchleife; end; Procedure TMyForm.SetSchleifenAbbruchErwuenscht (value : Boolean); begin ButtonAbbruch.Enabled := not Value; FButtonAbbruch := Value; End; Procedure TMyForm.MeineSchleife; begin SchleifenAbbruchErwuenscht := false; try while true do begin Application.ProcessMessages; if SchleifenAbbruchErwuenscht then break; DoSomething(); end; finally SchleifenAbbruchErwuenscht := false; end end; Procedure TMyForm.ButtonAbbruchClick(Sender : TObject); Begin SchleifenAbbruchErwuenscht := true; end;
Delphi-Quellcode:
wird auch der Click-Handler des
Application.ProcessMessages
Delphi-Quellcode:
ausgeführt. Dieser zeigt nun an, das ein Schleifenabbruch erwünscht ist.
ButtonAbbruch
Die Schleife bekommt das mit und kann sich beenden. Diese Property steuert gleichzeitig, ob der Button überhaupt klickbar ist. |
AW: Laufende whileschleife auf Knopfdruck unterbrechen
Zitat:
Wenn DU dort "false" setzt, dann ist der Button Enabled und signalisiert so fälschlicherweise dem Anwender, dass eine Schleife laufen würde. |
AW: Laufende whileschleife auf Knopfdruck unterbrechen
Dieses lässt sich insgesamt auch sehr schön generalisieren.
Eigentlich habe ich eine Aktion, die ausgeführt werden soll. Diese kann gestartet und während der Ausführung abgebrochen werden. Schön ist dann noch eine Benachrichtigung am Ende der Aktion. Erst vor kurzem wurde hier das Command-Pattern angesprochen, dass hervorragend dazu passt:
Delphi-Quellcode:
Eine Aktion würde demnach so aussehen:
ICommand = interface
function CanExecute : Boolean; procedure Execute; end;
Delphi-Quellcode:
Genau damit würde ich ansetzen. Ob die dann mit einem Thread oder eben mit
TActionResult = ( arCancelled, arException, arFinished );
TActionFinishedEvent = procedure ( Sender : TObject; ActionResult : TActionResult ); IAction = interface property StartCommand : ICommand; property CancelCommand : ICommand; property OnFinished : TActionFinishedEvent; end;
Delphi-Quellcode:
ist erst mal schnurz (Threads wären hier aber schon die richtige Wahl).
Application.ProcessMessages
|
AW: Laufende whileschleife auf Knopfdruck unterbrechen
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:13 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 by Thomas Breitkreuz