Einzelnen Beitrag anzeigen

TUX_der_Pinguin

Registriert seit: 1. Jun 2005
Ort: Anholt (NRW)
608 Beiträge
 
Delphi 11 Alexandria
 
#1

Anwendung sauber beenden bei Shutdown

  Alt 6. Dez 2010, 14:50
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
Angehängte Dateien
Dateityp: zip Shutdown-Test.zip (258,8 KB, 5x aufgerufen)
  Mit Zitat antworten Zitat