Recent

Author Topic: [SOLVED] progress dialog with blocked message queue  (Read 1797 times)

Phoenix

  • Full Member
  • ***
  • Posts: 135
[SOLVED] progress dialog with blocked message queue
« on: December 07, 2025, 05:06:47 pm »
Hi,
I'd like to enable a form to be displayed while performing operations that block the system message queue (I'm attaching the source code for testing). Currently, I only get the desired result if I call "Application.ProcessMessage" in the calculation loop. I'd like to avoid using it and still achieve something similar. Currently, the only way I can think of is using an external application called with a TProcess. Is there another way? The most important thing is to not add anything to the calculation loop to maintain maximum speed. Last consideration (already implemented but to be maintained) is the need to make the form appear only if I exceed a certain number of seconds of calculation, otherwise it should not appear. Thanks for any ideas, preferably platform-independent.
« Last Edit: December 07, 2025, 07:49:12 pm by Phoenix »

cdbc

  • Hero Member
  • *****
  • Posts: 2600
    • http://www.cdbc.dk
Re: progress dialog with blocked message queue
« Reply #1 on: December 07, 2025, 05:39:22 pm »
Hi
Calculate in a worker-thread and update your gui / form with messages...
Simplest & easiest way to achieve what you're after...
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

Phoenix

  • Full Member
  • ***
  • Posts: 135
Re: progress dialog with blocked message queue
« Reply #2 on: December 07, 2025, 06:51:36 pm »
Yes, reverse reasoning is conceptually the simplest and most appropriate design choice. Thank you.

I'd be curious if a cross-platform generalization is possible, such as checking when the application is stalled (not responding).

cdbc

  • Hero Member
  • *****
  • Posts: 2600
    • http://www.cdbc.dk
Re: progress dialog with blocked message queue [SOLVED]
« Reply #3 on: December 07, 2025, 07:31:19 pm »
Hi
If you keep your worker-thread count <= processor-count on your machine (incl. the main thread!), then it won't be /non-responsive8-)
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

Phoenix

  • Full Member
  • ***
  • Posts: 135
Re: progress dialog with blocked message queue [SOLVED]
« Reply #4 on: December 07, 2025, 07:48:46 pm »
Thank you

cdbc

  • Hero Member
  • *****
  • Posts: 2600
    • http://www.cdbc.dk
Re: [SOLVED] progress dialog with blocked message queue
« Reply #5 on: December 07, 2025, 07:55:29 pm »
Hi
I just downloaded your test.zip and will try and put something together later tonight and tomorrow...
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

Phoenix

  • Full Member
  • ***
  • Posts: 135
Re: [SOLVED] progress dialog with blocked message queue
« Reply #6 on: December 08, 2025, 12:45:54 am »
Thanks for your interest. In any case, here's a second initial version following the new approach. The problem is that in real-world use, it's problematic when there are many calculation parameters, etc., and requires more or less lengthy modifications. It would be easier if you could use it as a simple "try finally" block.

cdbc

  • Hero Member
  • *****
  • Posts: 2600
    • http://www.cdbc.dk
Re: [SOLVED] progress dialog with blocked message queue
« Reply #7 on: December 08, 2025, 01:14:35 am »
Hi
Use a record with all the parameters you need and feed that to your thread / calcule-procedure...
If you use 'PostMessage()' for your comms, you shouldn't need synchronization, but YMMV.
...And don't forget -- Gui-code in threads (apart from mainthread) -- is
 an ABSOLUTE NO-GO!!!

The LCL is NOT threadsafe!
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

Xenno

  • Jr. Member
  • **
  • Posts: 51
    • BS Programs
Re: [SOLVED] progress dialog with blocked message queue
« Reply #8 on: December 08, 2025, 04:58:10 am »
I usually use a trick to execute a thread which I need to wait it to finish. I use a "Please wait" form that is called with ShowModal. This form's onShow event I create and run the thread.

When the thread finished, this form will handle by thread's onTerminate for example. Then, the form close itself and return ModalResult (eg. mrOK or mrCancel) based on thread result.

This way, the app won't get Not Responding flag from OS while the UI is blocked. It can be extended to allow aborting the thread execution.
Lazarus 4.0, Windows 10, https://www.youtube.com/@bsprograms

Thaddy

  • Hero Member
  • *****
  • Posts: 18729
  • To Europe: simply sell USA bonds: dollar collapses
Re: [SOLVED] progress dialog with blocked message queue
« Reply #9 on: December 08, 2025, 08:11:14 am »
A modal form is blocking for the main thread....
If the modal form is IN the thread, cdbc' s warnings apply.
TThread has class methods that can report back status, if required.
This is not difficult at all.
See the examples in the manual:
https://www.freepascal.org/docs-html/rtl/classes/tthread.executeinthread.html
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

Xenno

  • Jr. Member
  • **
  • Posts: 51
    • BS Programs
Re: [SOLVED] progress dialog with blocked message queue
« Reply #10 on: December 08, 2025, 10:53:19 am »
A modal form does not block the main or caller thread itself—it only blocks the UI of the main or caller form. This is why the operating system does not mark the application as Not Responding and protecting something for example unexpected button click in main form while the thread is still running.

The typical flow looks like this:

FormMain -> FormProgress -> WorkerThread -> FormProgress -> FormMain

FormProgress can display status or progress updates using a synchronized method from the running worker thread, while also providing a chance for user to cancel or terminate the worker thread. 

I’ve been using this technique, for example, when loading large files, and it works well to keep the UI responsive while still allowing cancellable background processing.

Anyway "progress dialog" fits perfectly for modal form. But, yes, this is only a suggestion.
Lazarus 4.0, Windows 10, https://www.youtube.com/@bsprograms

Phoenix

  • Full Member
  • ***
  • Posts: 135
Re: [SOLVED] progress dialog with blocked message queue
« Reply #11 on: December 08, 2025, 11:02:07 am »
Hi
Use a record with all the parameters you need and feed that to your thread / calcule-procedure...
If you use 'PostMessage()' for your comms, you shouldn't need synchronization, but YMMV.

Yes, with a pointer you can pass everything (as placed in the code even if in the case of the test it is not needed). You just have to add more code for each use, but you can't do it otherwise, putting the calculations in the thread.

...And don't forget -- Gui-code in threads (apart from mainthread) -- is
 an ABSOLUTE NO-GO!!!

The LCL is NOT threadsafe!

Of course, this is just some preliminary code for testing.

I usually use a trick to execute a thread which I need to wait it to finish. I use a "Please wait" form that is called with ShowModal. This form's onShow event I create and run the thread.

When the thread finished, this form will handle by thread's onTerminate for example. Then, the form close itself and return ModalResult (eg. mrOK or mrCancel) based on thread result.

This way, the app won't get Not Responding flag from OS while the UI is blocked. It can be extended to allow aborting the thread execution.
Thanks @Xenno. The goal here is to automatically display a waiting form, but only when the calculation time exceeds n seconds. Otherwise, I find it annoying to have it disappear instantly or have to slow it down. In any case, the most annoying thing is seeing the dialog when it's not needed. This compensates, for example, when a user uses the program on a faster or slower computer.

A modal form is blocking for the main thread....
If the modal form is IN the thread, cdbc' s warnings apply.
TThread has class methods that can report back status, if required.
This is not difficult at all.
See the examples in the manual:
https://www.freepascal.org/docs-html/rtl/classes/tthread.executeinthread.html

Yes, the examples are clear. Thanks @Thaddy.

A modal form does not block the main or caller thread itself—it only blocks the UI of the main or caller form. This is why the operating system does not mark the application as Not Responding and protecting something for example unexpected button click in main form while the thread is still running.

The typical flow looks like this:

FormMain -> FormProgress -> WorkerThread -> FormProgress -> FormMain

FormProgress can display status or progress updates using a synchronized method from the running worker thread, while also providing a chance for user to cancel or terminate the worker thread. 

I’ve been using this technique, for example, when loading large files, and it works well to keep the UI responsive while still allowing cancellable background processing.

Anyway "progress dialog" fits perfectly for modal form. But, yes, this is only a suggestion.

With the current implementation, I should also keep user actions "blocked." Given the use of "Application.ProcessMessages," a user tired of waiting might click around, causing problems  ::).

Thaddy

  • Hero Member
  • *****
  • Posts: 18729
  • To Europe: simply sell USA bonds: dollar collapses
Re: [SOLVED] progress dialog with blocked message queue
« Reply #12 on: December 08, 2025, 11:34:32 am »
A modal form does not block the main or caller thread itself—it only blocks the UI of the main or caller form.
This is plainly not true, at least on Windows. It blocks the thread it is running in, usually the main thread completely, not only GUI elements.
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

cdbc

  • Hero Member
  • *****
  • Posts: 2600
    • http://www.cdbc.dk
Re: [SOLVED] progress dialog with blocked message queue
« Reply #13 on: December 08, 2025, 01:57:55 pm »
Hi Phoenix
As promised, here's a little project for you to play with...
It sort of works  :-[ Haven't gotten the delayed showing of progress to work yet though  ...I t shows right away  :-X
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

Phoenix

  • Full Member
  • ***
  • Posts: 135
Re: [SOLVED] progress dialog with blocked message queue
« Reply #14 on: December 08, 2025, 05:04:16 pm »
As promised, here's a little project for you to play with..

Thanks for this implementation  :)

Here I'm using Windows 10 with Laz 3.6 FPC 3.2.2 and it doesn't work properly. In particular, it stops almost at the end, not completing the button re-enablement, and it doesn't hide the dialog. I tried a couple of codes, but what makes it work is adding a sleep() like this:

Code: Pascal  [Select][+][-]
  1. function Calc(aHandle, n: ptruint): ptruint;
  2. var
  3.  i: LongInt;
  4. begin
  5.  Result:= 1;
  6.  for i:= 2 to n do begin
  7.   Result:= Result+i;//("+" just to avoid overflow for the generic test)
  8.   if i mod 200000 = 0 then
  9.   begin
  10.    PostMessage(aHandle,LM_ThreadUpdate,n,i);
  11.    Sleep(100);//<--
  12.   end;
  13.  end;
  14. end;
  15.  

It sort of works  :-[ Haven't gotten the delayed showing of progress to work yet though  ...I t shows right away  :-X

Don't worry :D. Perhaps keep the dialogue hidden, record the time at startup, and check with each update whether it's time to show the dialogue. Even if it's less precise, you avoid using an additional thread.

 

TinyPortal © 2005-2018