Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi OnTimer und Programm beenden (https://www.delphipraxis.net/100813-ontimer-und-programm-beenden.html)

Bea 4. Okt 2007 10:19


OnTimer und Programm beenden
 
Hallo,
ich hab ein Programm, welches sich nach dem Start mit der Komponente CoolTrayIcon in den Tray minimiert.
Mit einem Linksklick auf das Icon zeige ich mein Programm am Bildschirm an.
Mit einem Rechtsklick auf das Icon wird ein Kontexmenü mit dem Button "Beenden" sichtbar
und beim Klick auf das "Beenden" soll das Programm auch richtig beendet werden.
Das klappt auch soweit erstmal.
Nun mein Problem:
Mein Programm enthält einen Timer, der z. B. alle 5 Sekunden eine Schleife ausführt.
Klicke ich nun rechts auf meinen Beenden-Button im Tray um das Programm zu beenden,
wird beim Debuggen das OnTimer-Ereignis auch nocheinmal durchlaufen und dann passiert gar nichts,
erst wenn ich ein zweites Mal darauf geklickt habe, wird mein Programm beendet.
Woran kann das liegen?
Wieso wird das OnTimer- Ereignis nochmals durchlaufen, obwohl ich im Beenden1Click den Timer1.Enabled:=False gesetzt habe?
Und wieso wird das Programm dann nicht gleich beendet?

Hier ein paar vereinfachte Quelltextausschnitte:
Delphi-Quellcode:
// ONTIMER-EREIGNIS
procedure TForm_Connector.Timer1Timer(Sender:TObject);
begin
 Timer1.Enabled:= False; // Timer erstmal ausschalten und die Verzeichnis abarbeiten
 if bBeenden=False then
 begin
   ...
  // hier wird nun verschiedenes Zeug abgearbeitet
  // z. B. alle Dateien eines Verzeichnisses in ein anderes Verzeichnis verschieben

  Timer1.Enabled:= True; // Timer nun wieder einschalten
 end;
end;

// BEENDEN-KLICK
procedure TForm_Connector.Beenden1Click(Sender:TObject);
begin
 Timer1.Enabled:=False;
 bBeenden:= true;
 ExplicitClose:= True; // Programm soll richtig beendet werden
 self.close;
end;

// PROGRAMM IN DEN TRAY MINIMIEREN
procedure TForm_Connector.Fensterschlieen1Click(Sender:TObject);
begin
 ExplicitClose:= False;
 // Programm soll nicht beendet werden, sondern nur wieder im Tray verschwinden
 self.close;
end;

// PROGRAMM IN DEN TRAY MINIMIEREN ODER BEENDEN
procedure TForm_Connector.FormCloseQuery(Sender:TObject;
 var CanClose:Boolean);
begin
 if ExplicitClose then
  begin
   CanClose:= True;
   exit;
  end;
 //  Programm soll nur über das MenüItem "Beenden" oder über das TrayIcon "Beenden" beendet werden
 //  beim schließen des Fensters über das Kreuz der Form soll das Programm weiter im Tray laufen und nicht beendet werden
 CanClose:= False;
 CoolTrayIcon1.HideMainForm;
end;
Besten Dank im Vorraus!
CU Bea

shmia 4. Okt 2007 10:32

Re: OnTimer und Programm beenden
 
Man kann der VCL über Application.Terminate mitteilen, dass die Anwendung beendet werden soll.
Die Anwendung wird allerdings nicht sofort beendet, sondern kann noch weiterlaufen.
Mit if Application.Terminated then ... lässt sich an strategischen Stellen überprüfen,
ob man nicht eigentlich mit der Arbeit sofort aufhören sollte.
Delphi-Quellcode:
procedure TForm_Connector.Beenden1Click(Sender:TObject);
begin
  Timer1.Enabled:=False;
  bBeenden:= true;
  Application.Terminate; // <===
  close;
end;

// PROGRAMM IN DEN TRAY MINIMIEREN ODER BEENDEN
procedure TForm_Connector.FormCloseQuery(Sender:TObject;
var CanClose:Boolean);
begin
  CanClose := Application.Terminated; // <====
  if not CanClose then
//  Programm soll nur über das MenüItem "Beenden" oder über das TrayIcon "Beenden" beendet werden
//  beim schließen des Fensters über das Kreuz der Form soll das Programm weiter im Tray laufen und nicht beendet werden
    CoolTrayIcon1.HideMainForm;
end;

procedure TForm_Connector.Timer1Timer(Sender:TObject);
begin
  Timer1.Enabled:= False; // Timer erstmal ausschalten und die Verzeichnis abarbeiten
  if Application.Terminated then Exit; // <====
   ...
  // hier wird nun verschiedenes Zeug abgearbeitet
  // z. B. alle Dateien eines Verzeichnisses in ein anderes Verzeichnis verschieben

  Timer1.Enabled:= True; // Timer nun wieder einschalten
end;

Bea 4. Okt 2007 11:37

Re: OnTimer und Programm beenden
 
Vielen Dank für die schnelle Antwort.
Das klappt ja auch prima.
Kann ich mir aber sicher sein, dass eine begonnene Verarbeitung in einem umfangreicheren Schleifendurchlauf im OnTimer-Ereignis
auch erst vollständig abgearbeitet wird, eh sich das Programm wirklich beendet?
Ist das damit gegeben, dass ja immer zu Beginn des eintretenden OnTimer-Ereignisses
if Application.Terminated then Exit;
aufgerufen wird?

Danke Bea

DeddyH 4. Okt 2007 12:02

Re: OnTimer und Programm beenden
 
Wenn Du erst einmal in die Abarbeitung hineinkommst, wird diese auch durchlaufen. Beim nächsten Timer-Ereignis wird ja erst wieder geprüft, ob das Programm geschlossen werden soll und dieses ggf. vor der erneuten Abarbeitung verlassen.

shmia 4. Okt 2007 12:06

Re: OnTimer und Programm beenden
 
Zitat:

Zitat von Bea
Kann ich mir aber sicher sein, dass eine begonnene Verarbeitung in einem umfangreicheren Schleifendurchlauf im OnTimer-Ereignis
auch erst vollständig abgearbeitet wird, eh sich das Programm wirklich beendet?
Ist das damit gegeben, dass ja immer zu Beginn des eintretenden OnTimer-Ereignisses
if Application.Terminated then Exit;
aufgerufen wird?

Du kannst dann sicher sein, wenn du während der Arbeit im OnTimer-Eventhandler nicht Application.ProcessMessages aufrufst.
Sollte diese Arbeit länger dauern (Schleife) dann sollte man doch prüfen, ob man diese nicht vorzeitig beenden kann. (if Application.Terminated then Exit)
Wenn die Arbeit zu lange dauert (>= 1s) entsteht beim Benutzer das Gefühl, das Programm habe sich aufgehängt.

Reinhard Kern 4. Okt 2007 15:03

Re: OnTimer und Programm beenden
 
Zitat:

Zitat von Bea
...
Und wieso wird das Programm dann nicht gleich beendet?
...
CU Bea

Hallo,

es gibt keinen direkten Sprung in den Exit-Code oder sowas, das würde wohl einiges durcheinanderbringen. Der Auftrag, das Programm möge sich beenden, wird wie andere Botschaften an die Message Loop angehängt, u.U. nach einer schon eingereihten Timermessage. So wird ordentlich ein Fenster der Anwendung nach dem anderen geschlossen, das kann ja etwas dauern.

Gruss Reinhard

Bea 5. Okt 2007 07:38

Re: OnTimer und Programm beenden
 
Vielen Danke für eure Antworten.
Hab jetzt an verschiedenen Stellen (vor einer längeren Verarbeitung und danach)
if Application.Terminated then Exit;
eingebaut, da kann zwischendurch nichts schief gehen denk ich.
Bis jetzt klappt alles prima.
Also nochmals vielen Dank für die Hilfe!
Bea

SirThornberry 5. Okt 2007 07:49

Re: OnTimer und Programm beenden
 
der richtige Ansatz wäre beim Beenden-Klick den Timer abzuschalten damit er beim debugge nicht doch nochmal anspringt. Und im OnTimer wäre das abschalten und spätere wieder anschalten auch sinnvoll falls die OnTimerRoutine zu lange benötigt damit sich die Events nicht aneinanderreihen und überhäufen:
Delphi-Quellcode:
procedure TClass.TimerProc(Sender: TObject);
begin
  Timer.Enabled := False;
  //DoAnything
  Timer.Enabled := not(Application.Terminated);
end;

peschai 5. Okt 2007 07:51

Re: OnTimer und Programm beenden
 
Hallo,

Zusatzfrage zu diesem Umfeld:
Ich glaube (ok sollte man in die Kirche gehen :stupid:) daß auch ein
Delphi-Quellcode:
Update;
ähnlich wirkt wie
Delphi-Quellcode:
Application.ProcessMessages;
. Also eventuell hier ebenfalls aufpassen bei Schleifen. (Bin mir aber nicht zu 100% sicher)


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:37 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