AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung
Thema durchsuchen
Ansicht
Themen-Optionen

Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

Ein Thema von Der schöne Günther · begonnen am 23. Dez 2015 · letzter Beitrag vom 24. Dez 2015
Antwort Antwort
Der schöne Günther

Registriert seit: 6. Mär 2013
6.196 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 24. Dez 2015, 06:48
Vielen Dank für die Antworten bislang.

musst du das währen der WM_ENDSESSION Nachricht machen.
Aber das tue ich doch. In "Halt" beendet sich Delphi sogar mit ExitProcess selbst anstatt darauf zu warten dass Windows es tut. De facto antwortet die Anwendung nie auf WM_ENDSESSION, sondern schießt sich selbst vorher ab. Was ja auch an sich nicht verkehrt ist.

Und wenn du etwas erledigen musst, das länger dauert, musst du Windows das mitteilen. Du kannst dich entsprechend registrieren und wirst dann auch auf dem Herunterfahren-Bildschirm angezeigt in der Liste der Anwendungen, die das Herunterfahren blockieren.
Du meinst ShutdownBlockReasonCreate(..), richtig? Ich versuche es nochmal, das hat aber keinen Unterschied gemacht.
Vielleicht könnte es doch helfen, denn vielleicht gelten die von Uwe angesprochenen fünf Sekunden ja nachträglich wenn die Anwendung plötzlich kein sichtbares Fenster mehr hat:
die Windows wartet, bis es eine Anwendung als unresponsive einfach killt.
Aber ich kann die "Sleep"-Zeit im Beispiel auch auf 15 Sekunden hochdrehen. Das zweite "ZZzz" wird trotzdem immer problemlos auf die Platte gespeichert. Das Problem ist nicht die Zeit, sondern das, was durch "Halt" in irgendeiner der Unit-Finalisierungen passiert...



Wir haben keinerlei wichtigen Code in finalization drin. In finalization passieren nur noch Sachen, auf die wir keinen Einfluss haben (Delphi-Units, 3rd-Party Units, ...).
Das heißt theoretisch müsste man sagen "Unit-Finalisierung und Klassen-Destruktoren: Naja- Können ausgeführt werden, vielleicht aber auch nicht."?
Wir haben leider durchaus Anwendungen welche im Klassen-Destruktor noch beispielsweise Dateien flushen und schließen. Jetzt im Nachhinein zu sehen dass höchstwahrscheinlich nicht ausgeführt wird wenn Windows heruntergefahren wird und die Anwendung noch offen ist schockiert mich ehrlich gesagt etwas ziemlich.

Sorg dafür, dass da nichts wichtiges mehr passiert.
Wie soll das gehen? Ich könnte nach WM_QUERYENDSESSION schon anfangen die Zelte abzubauen, aber helfen tut mir das im Endeffekt doch auch nichts...


Meine Vermutung zur Ursache des vorzeitigen Ablebens bleibt weiterhin dass irgendeine Unit-Finalisierung der VCL/RTL weiterhin in der Nachrichtenschleife der Anwendung wühlt und Windows die Anwendung darauf hin direkt killt.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 24. Dez 2015, 09:40
musst du das währen der WM_ENDSESSION Nachricht machen.
Aber das tue ich doch. In "Halt" beendet sich Delphi sogar mit ExitProcess selbst anstatt darauf zu warten dass Windows es tut. De facto antwortet die Anwendung nie auf WM_ENDSESSION, sondern schießt sich selbst vorher ab. Was ja auch an sich nicht verkehrt ist.
Du sagst, dass du deiner Anwendung schon selber ein WM_ENDSESSION geschickt hast.

Wie schickst du denn? Mit SendMessage ?
Dann bleibt also diese sendende Anwendung hängen? (Weil SendMessage blockiert, bis es eine Rückmeldung bekommt)

Oder bekommst du dort doch eine Rückmeldung?

Einfach mal ausprobieren und ich wette, da kommt etwas zurück
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#3

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 24. Dez 2015, 10:09
Nur mal so al "Spekulatius":

Warum Halt?

Würde das Programm lieber "regulär" beenden, statt Halt(0); mit Application.MainForm.Close; .
Beende meine Programme eigentlich immer damit, dass ich das Hauptformular schließe.

Die Hilfe von Delphi 7 sagt zu Halt:
Zitat von Delphi-Hilfe:
Beschreibung

Die Prozedur Halt löst einen Programmabbruch aus und gibt die Steuerung an das Betriebssystem zurück.
und genau das scheint ja auch zu passieren. Warum soll denn dann noch was ausgeführt werden?

Ansonsten: Wie wäre es mit dem ebenfalls in der Hilfe beschriebenen:
Zitat von Delphi-Hilfe:
Beschreibung

Rufen Sie Terminate auf, um die Anwendung programmgesteuert zu beenden. Durch einen Aufruf der Methode Terminate wird das Anwendungsobjekt nicht einfach gelöscht, die Anwendung kann vielmehr ordnungsgemäß heruntergefahren werden.
Also Application.Terminate; ?

Warum das Programm "brutal" mit Halt beenden, wenn es auch moderat geht?
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 24. Dez 2015, 10:15
Warum das Programm "brutal" mit Halt beenden, wenn es auch moderat geht?
Weil Borlacadero das so in procedure TApplication.WndProc(var Message: TMessage); programmiert hat?
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.196 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 24. Dez 2015, 10:23
Hört sich an wie eine Darmerkrankung

// 1. Update

Und mein Verdacht erhärtet sich! Wenn ich in meinem WM_ENDSESSION das Hauptformular abbaue, wird die Anwendung von Windows gekillt. Er scheint wirklich zu meinen "So, sind ja alle Fenster weg, können wir hier ja zumachen". Ein einfaches Form1.Destroy() reicht schon, alles danach wird nicht mehr ausgeführt!

Was ist nun wenn wir das Hauptformular nicht zerstören? Wie Raymon Chen schon sagte:
Zitat:
Besides, why spend your time closing windows when the session is about to go away anyway? Ooh, let me clean up this and destroy that, I know you asked to shut down, but this’ll just take a few seconds. It’s like taking the time to steam-clean the rugs before you demolish the building. Wasted effort.
Mein QuickFix sieht so (schlimm) aus:

Delphi-Quellcode:
destructor TForm1.Destroy;
begin
   if (Application.MainForm = self) then
      // do nothing
   else
      inherited;
end;
Was geschieht dann? Alles was ich möchte. Die Anwendung wird ordentlich beendet, die Dinge im finalization-Abschnitt der Unit werden ausgeführt und der Klassendestruktor auch. War es doch so einfach?


// 2. Update

Und die Bestätigung ist wohl auch da. Die Anwendung geht reproduzierbar tot wenn ich beim Herunterfahren nur sage WinApi.Windows.DestroyWindow(Form1.Handle); Tja, die Doku zu WM_ENDSESSION sagte
Zitat:
The application need not call the DestroyWindow or PostQuitMessage function when the session is ending.
"Need not call" ist nach meinem Englisch "muss nicht".

Hätte ich Idiot ausnahmsweise mal die Kommentare auf der MSDN-Seite weiter unten geleasen. Ein werter Herr bestätigt exakt meine Erlebnisse:
Zitat:
The documentation says you need not call DestroyWindow() inside your WM_ENDSESSION handler, but in my experience you *must* not call DestroyWindow(). Otherwise, the system might nuke your process before DestroyWindow() returns.
Das ist es also. Was wäre nun ein ordentliches Ende für diese Odyssee? Ich tue mich schwer auf eine konkrete Stelle im VCL-Code zu zeigen und zu sagen "Das sollte anders gemacht werden".

Geändert von Der schöne Günther (24. Dez 2015 um 11:58 Uhr)
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.196 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 24. Dez 2015, 10:15
Halt nehme ich da es
1. Die VCL auch von selbst so macht (siehe weiter unten)
2. Ich keine andere Möglichkeit kenne die Units finalisieren zu lassen


Einfach mal ausprobieren und ich wette, da kommt etwas zurück
Uh, nein, da kommt gar nichts zurück. Die Vcl sagt standardmäßig:

Delphi-Quellcode:
Vcl.Forms.TApplication.WndProc(..)
begin
   [...]
   WM_ENDSESSION:
      begin
         [...]
         if EndSessionMsg.EndSession then begin
            Application.Terminate;
            Halt;
            end;
   [...]
end;
Halt ist, soweit ich weiß, die einzige Möglichkeit, die Unit-Finalisierung aufzurufen.

System.Halt sagt:

Delphi-Quellcode:
procedure _Halt0;
begin
   [...]
   FinalizeUnits;
   [...]
   WinApi.Windows.ExitProcess(ExitCode);
end;
Eine VCL-Anwendung antwortet somit nie auf ein WM_ENDSESSION , sondern schießt sich vorher ab. Klingt komisch, ist aber doch völlig legitim. Ich denke eher das Abräumen der Formulare sorgt dafür dass Windows denkt "So, der ist ja durch. Weg mit dem".

Ich versuche mal, schon alle Formulare in WM_QUERYENDSESSION zu zerstören. Vielleicht bringt das ja was...

Geändert von Der schöne Günther (24. Dez 2015 um 10:19 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:40 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-2025 by Thomas Breitkreuz