Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   eigenartiges Verhalten bei Onclose eines Formulars (https://www.delphipraxis.net/213873-eigenartiges-verhalten-bei-onclose-eines-formulars.html)

SusiT 11. Okt 2023 22:29

eigenartiges Verhalten bei Onclose eines Formulars
 
Guten Abend.

Mir ist ein eigenartiges Verhalten beim Ablauf des Schließens eines Formulars aufgefallen und mich interessiert ob dieses Verhalten bekannt ist.


Der normale Ablauf bei Schließen eines Formulars ist in der Regel folgender:


onClose Event wird ausgelöst (Klick auf Kreuz)

Formularvariable wird Released -> Event wird erzeugt

OnDestroy Prozedur wird aufgerufen


In OnDestroy werden alle möglichen Objekte FreeAndNil gesetzt und die Speicherbereinigung findet statt.


Ich habe ein sehr komplexes Formular mit sehr viel Inhalt.

Jetzt das komische Verhalten:

In bestimmten Konstellationen schaffe ich es, dass das Formular schneller schließt als es tatsächlich seinen eigenen Code durchläuft und abarbeitet.
Wenn ich während der Abarbeitung einer Prozedur des Formulars das Formular schließe (eine Prozedur die eben mehr Zeit benötigt) , dann wird OnDestroy schneller erreicht und ausgeführt als die Abarbeitung der Prozedur die noch in Arbeit ist.
Das hat nen blöden Nebeneffekt. In OnDestroy werden Objekte auf nil gesetzt, die in der noch nicht fertigen Prozedur verwendet werden. Die Folge ist eine Exception mit Zugriffsverletzung und einer ganzen Menge anderer unschöner Fehler.

Jetzt frage ich mich, wie kann ich in oder vor Destroy erkennen, dass noch irgendwelcher Code bearbeitet wird?

Ähnlich wie bei waitfor im Threading.

Dieses parallele Verhalten deutet auch darauf hin, das hier 2 Threads am Laufen sein müssen? Main Thread vom Formular und ein Schließen Thread?



Viele Grüße

himitsu 11. Okt 2023 22:45

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Erstens: Man ruft nicht Destroy auf, sondern Free. Und bei Forms besser Release.
Ist die Form Modal, dann nur Close und niemals Destroy/Free oder Dergleichen.

Wie viel wollen wir wetten, dass du irgendwo ein Application.ProcessMessages, Application.HandleMessage, ShowMessage oder Dergleichen aufrufst, welches Messages mitten der Behandlung ausführt, anstatt erst anschließend?

BerndS 12. Okt 2023 06:07

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Eine Lösung, um das Close während der Ausführung der Prozedur zu verhindern wäre, das Ereignis TForm.OnCloseQuery zu nutzen und hier CanClose auf false zu setzen, wenn die Prozedure noch nicht fertig ist. Dazu wäre eine Variable hilfreich, die besagt, ob die Prozedure noch aktiv ist.

Ich lasse länger laufende Prozeduren möglichst nie im Hautthread laufen.

himitsu 12. Okt 2023 07:13

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Wenn jemand aber bösartig Free/Destroy aufruft, dann wird OnCloseQuery ignoriert (nicht aufgerufen).

Destroy gibt das Objekt IMMER frei, egal ob jemand noch was abbrechen will (Exception/Abort/...)

fisipjm 12. Okt 2023 07:24

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Moin,

darf ich da mal einhacken.
Zitat:

Zitat von himitsu (Beitrag 1527995)
...Und bei Forms besser Release....

Ist
Delphi-Quellcode:
Release
nicht als
Delphi-Quellcode:
deprecated
geflagt? Oder ist das nur bei Firemonkey so? Normalerweise setzt man doch im
Delphi-Quellcode:
OnClose
Event der jeweiligen from den OnClose handle auf
Delphi-Quellcode:
caFree
und ruft dann einfach ein
Delphi-Quellcode:
Tform.Close
auf.
Da ich aber an der Stelle auch immer höchst unsicher bin, würd ich das gern nutzen um auch für mich mal Klarheit zu schaffen :-D

Grüße und einen guten Start in den Tag
PJM

dummzeuch 12. Okt 2023 07:55

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Zitat:

Zitat von himitsu (Beitrag 1527995)
Erstens: Man ruft nicht Destroy auf, sondern Free. Und bei Forms besser Release.

Release ist dazu gedacht, um aus einem Event des Formulars aufgerufen zu werden, so dass es erst freigegeben wird, wenn der Event beendet wurde. In allen anderen Situationen sollte man Free aufrufen.


Zitat:

Zitat von himitsu (Beitrag 1527995)
Wie viel wollen wir wetten, dass du irgendwo ein Application.ProcessMessages, Application.HandleMessage, ShowMessage oder Dergleichen aufrufst, welches Messages mitten der Behandlung ausführt, anstatt erst anschließend?

Vermutlich korrekt.

SusiT 12. Okt 2023 08:16

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Die Form ist nicht mit ShowModal geöffnet sondern nur mit Show.

Beim schließen der Form wird das onClose Event getriggert -> FormClose

in FormClose wird eine callback funktion des parents aufgerufen in welcher

form.Release;
form := nil;

gesetzt wird.

Bei Release wird das onDestroy Event getriggert und führt im Formular das geschlossen wird, die Prozedur FormDestroy auf.


So ist im Moment der Ablauf bei mir.

Danke für dein Wettangebot, allerdings muss ich passen. Ich habe jetzt schon das Gefühl, dass ich diese Wette verlieren würde :-D

Ich prüfe dies mal.

Gausi 12. Okt 2023 08:53

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Release ist doch dafür da, dass ein Form "geordnet" freigegeben werden kann, auch in eigenen Event-Handlern. Dann direkt auch die Formvariable zu nilen ist glaube ich keine besonders gute Idee. Das kann gut gehen, muss aber nicht.

Lass das mal weg, und merke dir anderweitig, ob das Formular ggf. später neu erzeugt werden muss oder nicht (also nicht per Test auf =Nil).

Kas Ob. 12. Okt 2023 09:08

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Zitat:

Zitat von SusiT (Beitrag 1528003)
Die Form ist nicht mit ShowModal geöffnet sondern nur mit Show.

Beim schließen der Form wird das onClose Event getriggert -> FormClose

in FormClose wird eine callback funktion des parents aufgerufen in welcher

form.Release;
form := nil;

gesetzt wird.

Bei Release wird das onDestroy Event getriggert und führt im Formular das geschlossen wird, die Prozedur FormDestroy auf.


So ist im Moment der Ablauf bei mir.

So you are not mentioning what the form has for "Action: TCloseAction" in FormClose, yet you releasing it from the MainForm !! :gruebel:

I suggest to use one method to close/release a form, not both at the same time, one method will do the job right, two will burn the meal for sure.

bcvs 12. Okt 2023 10:36

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Zitat:

Zitat von SusiT (Beitrag 1528003)
Die Form ist nicht mit ShowModal geöffnet sondern nur mit Show.

Beim schließen der Form wird das onClose Event getriggert -> FormClose

in FormClose wird eine callback funktion des parents aufgerufen in welcher

form.Release;
form := nil;

gesetzt wird.

Warum so kompliziert? Bei nicht modalen Forms brauchst du überhaupt kein destroy, free oder release.
Einfach nur:
Delphi-Quellcode:
procedure TMyForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;
Falls du die Formvariable noch brauchst, um zu überprüfen, ob die Form existiert, kannst du sie hier auch auf nil setzen.

SusiT 12. Okt 2023 20:22

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Natürlich hattet Ihr Recht und ich wäre der Verlierer bei der Wette gewesen:P


Ich habe es nun tatsächlich so simple wie möglich aufgebaut.

In FormClose:

Action := caFree;
FormVariable := nil;

und zusätzlich werden in FormClose alle Variablen und Speicherobjekte wieder freigegeben.


Besten Dank und vielen Dank für die rege Teilnahme beim großzügigen Verteilen von freiem Wissen :thumb:

himitsu 12. Okt 2023 20:56

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
FormClose?

Man gibt etwas an der Gegenstelle dessen frei, wo es erstellt wurde.

In OnClose also das, was im OnShow erstellt wurde. Hast du es wirklich dort erstellt?

PS: OnCreate->OnDestroy oder Create->Destroy aka Constructor->Destructor usw.

SusiT 12. Okt 2023 21:20

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Diese Konvention hatte ich bis dato noch nicht verinnerlicht.
Macht aber auch Sinn und werde das optimieren.8-)

Dann muss die globale Formvariable aber auch später auf nil gesetzt werden.

himitsu 12. Okt 2023 21:56

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Stell dir einfach mal zwei Fälle vor
* die Form erstellen und zwei Mal anzeigen (Show+HideClose oder ShowModal)
* die Form erstellen und garnicht anzeigen, sondern direkt wieder freigeben

1a. Beim zweiten Mal knallt's, weil die Form weg ist
1b. Beim zweiten Mal knallt's, weil im OnClose freigegeben wurde (natürlich ohne caFree, sondern mit caHide)
2. Es wird nie freigegeben, weil OnClose garnicht aufgerufen wird

DenkDirNix 13. Okt 2023 06:31

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Hm,
ich habe bisher OnHide als Gegenpart zum OnShow betrachtet.
Siehe hier: https://www.delphipraxis.net/156-abl...ormulares.html

jaenicke 13. Okt 2023 09:13

AW: eigenartiges Verhalten bei Onclose eines Formulars
 
Zitat:

Zitat von SusiT (Beitrag 1528029)
Dann muss die globale Formvariable aber auch später auf nil gesetzt werden.

Am besten setzt man diese im OnDestroy auf nil, denn danach existiert ja das Formular auch nicht mehr. Innerhalb des Formulars selbst sollte diese nie benutzt werden.


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