Hallo,
ich habe eine kleine Anwendung die per Timer eine Prozedur startet die einige Daten verarbeitet.
Will der Benutzer diese Anwendung beenden geht dies nur wenn die Prozedur nicht läuft. Der Anwender
kann die Prozedur anhalten, und dann das Programm beenden.
Wird jetzt der Computer heruntergefahren während die Prozedur läuft so soll sich die Prozedur beenden
und die Anwendung soll kurz warten bis die Prozedur durchgelaufen ist und dann soll der Computer
herunterfahren.
Der erste Teil funktioniert jedoch gibt es Probleme wenn der Computer heruntergefahren wird, so wird
zwar die Prozedur angehalten jedoch scheint die Prozedur nicht korrekt beendet worden zu sein. Es
scheint als würde er aus der Prozedur springen.
Um das besser zu verstehen habe ich eine kleine Testanwendung gebastelt die das gleiche Problem hat.
Ich habe den Timer durch einen Button ersetzt, der Button (btnStart) stößt die Prozedur "Routine" an.
Delphi-Quellcode:
unit uMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm4 =
class(TForm)
btnStart: TButton;
Edit1: TEdit;
btnCancel: TButton;
Edit2: TEdit;
procedure FormCreate(Sender: TObject);
procedure FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
procedure btnStartClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
procedure Routine;
procedure WMEndSession(
var Msg: TMessage);
message WM_ENDSESSION;
procedure WMQueryEndSession(
var Msg: TMessage);
message WM_QUERYENDSESSION;
private
{ Private-Deklarationen }
bShutdown: Boolean;
bStarted: Boolean;
bBreak: Boolean;
public
{ Public-Deklarationen }
end;
var
Form4: TForm4;
implementation
{$R *.dfm}
procedure TForm4.btnStartClick(Sender: TObject);
begin
Routine;
end;
procedure TForm4.btnCancelClick(Sender: TObject);
begin
//Flag zum Abbruch der Routine setzen
bBreak := True;
end;
procedure TForm4.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
begin
//Anwendung beenden ohne Nachfrage beim Shutdown
if bShutdown
then begin
CanClose := True;
end
else begin
//Läuft die Routine kann die Anwendung nicht beendet werden.
if bStarted
then begin
CanClose := False;
Application.MessageBox('
Das Programm kann nicht beendet werden!', '
Hinweis', 48);
end
else begin
//Routine läuft nicht, Anwender fragen ob Anwendung wirklich beendet werden soll
if Application.MessageBox('
Soll das Programm beendet werden?', '
Frage', 36) = ID_YES
then
CanClose := True
else
CanClose := False;
end;
{else}
end;
{else}
end;
procedure TForm4.FormCreate(Sender: TObject);
begin
//init
bShutdown := False;
bStarted := False;
bBreak := False;
end;
procedure TForm4.Routine;
var
Counter: Integer;
begin
//Routine wurde gestartet
btnStart.Enabled := False;
bStarted := True;
bBreak := False;
Edit1.Clear;
//Routine läuft...
Counter := 0;
while (Counter < 500000)
and not bBreak
do begin
Edit1.Text := IntToStr(Counter);
Inc(Counter);
Application.ProcessMessages;
end;
{while}
//Dieser teil wird nicht mehr ausgeführt beim Shutdown, warum auch immer
//Routine ist fertig, Flags zurücksetzen etc.
Edit1.Text := '
Fertig';
bStarted := False;
btnStart.Enabled := True;
end;
procedure TForm4.WMEndSession(
var Msg: TMessage);
begin
//Warten bis die Routine beendet wurde (Hier hängt die Anwendung, da bStarted nicht auf False gesetzt wird)
while bStarted
do begin
Edit2.Text := FormatDateTime('
hh:nn:ss:zzz', Now);
Application.ProcessMessages;
Sleep(100);
end;
{while}
//Bestätigung das Windows herruntergefahren wird
Msg.Result := 1;
end;
procedure TForm4.WMQueryEndSession(
var Msg: TMessage);
begin
//Computer soll herruntergefahren, neugestartet oder abgemeldet werden
bShutdown := True;
//Flag zum Abbruch der Routine setzen
bBreak := True;
//Bestätigung das Windows herruntergefahren werden darf
Msg.Result := 1;
end;
end.
Ich habe zwar diverse Beiträge gefunden zu dem Thema gefunden, da durch bin ich erst auf WM_QUERENDSESSION
etc. gestoßen. Ich konnte nur nichts vergleichbares finden.
Alle Beispiele haben erst in der Nachrichten Verarbeitung Routinen zum "Aufräumen" aufgerufen das
scheint wohl auch so zu klappen.
Nur wie bringe ich meinem Programm bei die Prozedur nicht zu verlassen sondern sauber sich zu beenden?
mfg
TUX
p.s. Entwicklungsumgebung ist Delphi 2009 Prof.
Anbei die Test-Anwendung