Recent

Author Topic: Automatic Free after setting 'CloseAction:=caFree' in TForm.OnClose-Event  (Read 451 times)

Hartmut

  • Hero Member
  • *****
  • Posts: 1028
Because my program caused a not reproducible Access Violation, I'm digging deep into my sources and found something strange having to do with the automatic Free(), which is executed after setting 'CloseAction:=caFree' in a TForm.OnClose-Event of a non modal shown Form. Therefore some questions occured (some I tried to ask in the Topic, which I'd started for this AV, but did not get there enough attention probably because of it's divergent subject):

When a non modal Form has an OnClose-Event-Handler and in it 'CloseAction:=caFree' is set:

a) which method is automatically executed to "free" the Form: is self.Free() called (which then calls self.Destroy(), if I'm correct) or is only self.Destroy() called, without self.Free()?

b) at which time will this Form be automatically free'd?
 - always immediately after the OnClose-Event exits?
 - or can/will this be (always) "later", e.g. when the next Application.ProcessMessages() is called (by my code or from the LCL) or when certain "messages" are handled by the LCL? My knowledge about these things is verry low, so some more details would be very helpful.
 - what is the latest possibility, when this Form is free'd?

c) are there any differences in your answers
 - if the Form is the MainForm or not?
 - if the Parent of the Form is var 'Application'?
 - if the Form was shown modal or non modal?

Sorry for so detailed questions. I'm checking & reworking a lot of code which has many different conditions. And now I want to definitely learn and understand this subject to avoid more uncertainnesses and mistakes/bugs in the future :-)
Thanks in advance.

wp

  • Hero Member
  • *****
  • Posts: 13267
Re: Automatic Free after setting 'CloseAction:=caFree' in TForm.OnClose-Event
« Reply #1 on: September 10, 2025, 07:45:44 pm »
(a, b) The form does not destroy itself immediately (that's what self.Free would be doing), but in a delayed way by means of the Release method. This puts the request for destruction into a queue which is handled when the application is idle.

(c1) MainForm.Close calls Application.Terminate in TForm.Close (see TCustomForm.Close). Sounds more drastic than it is: it just sets the FTerminated flag to true, i.e. does not terminate the application immediately. But FTerminated=true exits the Run loop and terminates the app then.
(c2) I think there is no difference
(c3) ModalForm.Close sets the Modalresult of the form to mrCancel (TCustomForm.Close). A non-zero ModalResult exits the ShowModal loop and finally closes the form via Release again.

Hartmut

  • Hero Member
  • *****
  • Posts: 1028
Re: Automatic Free after setting 'CloseAction:=caFree' in TForm.OnClose-Event
« Reply #2 on: September 11, 2025, 04:55:08 pm »
Thank you very much wp for this very helpful informations.

I did not know the TCustomForm.Release() method before, but found a remarkable detailed documentation in https://lazarus-ccr.sourceforge.io/docs/lcl/forms/tcustomform.release.html

Normally TCustomForm.Release() calls Application.ReleaseComponent(self), which is (also remarkable detailed) documentated in https://lazarus-ccr.sourceforge.io/docs/lcl/forms/tapplication.releasecomponent.html

Normally Application.ReleaseComponent() adds the given Component to an "internal list" and posts an "asynchronous application message" via TApplication.QueueAsyncCall(TApplication.FreeComponent).

TApplication.FreeComponent() calls TApplication.ReleaseComponents(), which in general calls Free() for all Components in above "internal list" - which answers my question a)

TApplication.QueueAsyncCall() inserts an asynchronous call into a queue, for whose execution time I found a couple of related wordings e.g.:
1) which is handled when the application is idle
2) for execution in the main event loop, when all other events have been processed
3) to be executed, after the current event has finished
4) to be executed, after all other messages have been processed.

This execution time is still somewhat nebulous for me...
 - does all 4 wordings mean exactly the same?
 - is here an "event" exactly the same as a "message"? (I know nothing about "Windows messages")
 - 2) and 3) differ regarding "all other events" and "the current event". Which is correct?

It would be great, if you (or someone else) could spend some more light on this execution time. Thanks a lot.

 

TinyPortal © 2005-2018