Einzelnen Beitrag anzeigen

TUX_der_Pinguin

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

AW: Anwendung sauber beenden bei Shutdown

  Alt 7. Dez 2010, 11:32
Guten Morgen,

nach reichlicher Überlegung und stundenlangem Probieren bin ich zu einer Lösung gekommen. Das Problem
war das das Warten auf Beendigung der Prozedur den Ablauf der Prozedur blockiert hat. Daher habe ich
die Routine in einen Thread verlagert. So ist es nun möglich diesen Thread vorzeitig zubeenden und auf
dessen Beendigung zu warten.

Delphi-Quellcode:
procedure TfrmMain.btnStartClick(Sender: TObject);
begin
  if not bThreadRunning then begin
    //Flag setzen, Thread wird erzeugt und gestartet
    bThreadRunning := True;

    //Buttons
    btnStart.Enabled := False;
    btnCancel.Enabled := True;

    //Thread Erzeugen
    UpdateThread := TUpdate.Create(True);
    UpdateThread.FreeOnTerminate := True;
    UpdateThread.Priority := tpNormal;
    UpdateThread.OnTerminate := UpdateThreadTerminate;
    UpdateThread.Resume;
  end;{if}

end;

//Merkwürdigerweise wird das Ereignis OnCloseQuery beim Shutdown nicht mehr ausgeführt, obwohl in
//der Richtigen Anwendung das der Fall war. Aber es ist ja ganz einfach möglich die Sicherheitsabfrage
//beim Shutdown zu überspringen
procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  //Anwender fragen ob Anwendung wirklich beendet werden soll
  if (Application.MessageBox('Soll das Programm beendet werden?', 'Frage', 36) = ID_YES) then begin

    //Falls Routine noch läuft wird diese beendet
    if bThreadRunning then begin
      //Thread beenden
      UpdateThread.Terminate;

      //Kurz warten bis der Thread sich beendet hat
      while bThreadRunning do begin
        Application.ProcessMessages;
      end;{while}
    end;{if}

    //Anwendung kann geschlossen werden
    CanClose := True;
  end
  else
    CanClose := False;

end;

//Dieses Ereignis wird sowohl beim Beenden durch den Anwender als auch beim Shutdown durchgeführt
//Das ist es was ich die ganze Zeit wollte, explizit die Routine beenden und entsprechen "aufräumen"
procedure TfrmMain.UpdateThreadTerminate(Sender: TObject);
begin
  //Routine wurde beendet
  bThreadRunning := False;
  Edit1.Text := 'Fertig';

  //Buttons
  btnStart.Enabled := True;
  btnCancel.Enabled := False;

  //deinitialisieren
  UpdateThread := nil;

  //Nur zu Testzwecken das man sehen kann das die Routine bis hierher "durchgelaufen" ist
  pDelay(1000);
end;

procedure TfrmMain.WMEndSession(var Msg: TMessage);
begin
  //Kurz warten bis der Thread sich beendet hat
  while bThreadRunning do begin
    Application.ProcessMessages;
  end;{while}

  //Bestätigung das der Computer herruntergefahren wird
  Msg.Result := 1;
end;

procedure TfrmMain.WMQueryEndSession(var Msg: TMessage);
begin
  //Falls Routine läuft muss diese abgebrochen werden
  if bThreadRunning then UpdateThread.Terminate;

  //Bestätigung das Windows herruntergefahren werden darf
  Msg.Result := 1;
end;
Die eigentliche Routine die die Arbeit erledigt steht im Thread und sieht wie folgt aus.
Delphi-Quellcode:
procedure TUpdate.Execute;
begin
  while (Counter < 500000) and not Terminated do begin
    Synchronize(Show);
    Inc(Counter);
  end;{while}
end;
Anbei noch mal das gesamte Test-Projekt.

Vielen dank für die Tipps und Anregungen.

MFG

TUX
Angehängte Dateien
Dateityp: zip Shutdown-Test.zip (263,8 KB, 23x aufgerufen)
  Mit Zitat antworten Zitat