Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: How to move code to a child thread for the sake of having a UI showing status



Permlink Replies: 6 - Last Post: Nov 7, 2014 9:06 AM Last Post By: Eduardo Elias
Eduardo Elias

Posts: 319
Registered: 9/20/12
How to move code to a child thread for the sake of having a UI showing status
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 2, 2014 4:48 PM
[xe6 fmx windows]

I have wake up only now that i should have projected my code to move processing
code to thread and let my main thread responsive for UI updates

That is not trivial at this point

Since I am using a lot of livebindings and it will make the controls update.
So I need to be on the MainThread.

I was wondering if there is a way to start a thread and wait it end like:

ExecuteThreadAndWaititFinishes(<call to my actual code that opens databases
and cause controls to be updated>)

So my point here is to move all execution needed, where I know it is heavy,
to a child thread, only to keep the main thread free to update the ui (and
to update a progress bar on FMX)

AND to not move to the next line while it is not completed. Since the code
is no prepared for working in parallel, specially due to the UI update from
the child thread. So I was thinking if I could keep the MainThread doing
almost nothing it would not cause conflict with the child thread, and it
would keep the reponsiveness to update the progressbar, at least on the heaviest
processing places.

Any Ideas?

Eduardo

Peter Below

Posts: 1,227
Registered: 12/16/99
Re: How to move code to a child thread for the sake of having a UI showing status
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 3, 2014 10:55 AM   in response to: Eduardo Elias in response to: Eduardo Elias
Eduardo Elias wrote:

[xe6 fmx windows]

I have wake up only now that i should have projected my code to move
processing code to thread and let my main thread responsive for UI
updates

That is not trivial at this point

Since I am using a lot of livebindings and it will make the controls
update. So I need to be on the MainThread.

I was wondering if there is a way to start a thread and wait it end
like:

ExecuteThreadAndWaititFinishes(<call to my actual code that opens
databases and cause controls to be updated>)

So my point here is to move all execution needed, where I know it is
heavy, to a child thread, only to keep the main thread free to update
the ui (and to update a progress bar on FMX)


The thread will have to do the UI updating via Synchronize usually (to
execute it in the main thread context).
That makes waiting for it to finish a bit complex, but it can be done.
However, whether it will actually give you a benefit depends on how
much of its real processing time the thread spends in fetching the data
from the database and how much time the UI updates use.

There is an additional problem: database connections are usually tied
to the thread that created them. This depends on the database you
connect to and the connection components you use. So, executing a query
in a secondary thread and then using the retrieved data in the main
thread may be problematic, unless you can store the data into a data
structure of your own inside the thread first, and update the UI from
that data structure, not from the query component itself.

OK, now to answer your question: how you go about this depends on how
you want to design the thread. If it is to be a one action thread (you
create it, it executes its Execute method and exits that when the task
has completed, then you destroy the thread object) you can wait on the
thread's Handle directly. If the thread should be able to process tasks
whenever you have one for it to work on it would have a loop inside
Execute that waits for tasks to arrive, and signal completion by means
of a TSimpleEvent or similar object. In this case you would wait on the
handle of the event object.

The wait has to be done using the API function
MsgWaitForMultipleObjectsEx on Windows, which allows the wait to wake
up when a message to the waiting thread is received. I have no idea how
to do the equivalent on non-Windows platforms, sorry.

To show the principle i'll give you an example from my threading
library. The task object waits on an event in this case (FSignal is a
TSimpleEvent). You will not be able to directly use this code, of
course, but it should clearify the approach. The ProcessPendingMessages
procedure will also get Synchronized calls processed, since those are
triggered by a posted message.

If you want to use my threading library for your problem, go here
https://forums.embarcadero.com/thread.jspa?threadID=107478&tstart=0 and
download the attached archive, it has the relevant units.

{! Wait for the call to complete. Optionally we can process a subset
of messages during the wait. That complicates the timeout handling,
though, since the wait can be interrupted by messages.}
function TAsyncCall.WaitForCompletion(TimeoutMSecs: Cardinal;
ProcessMessages: Boolean): TWaitResult;
var
TargetTime, CurrentTime: int64;
H: THandle;
Ret: DWORD;

function TimeRemaining: DWORD;
begin
if TimeoutMSecs = INFINITE then
Result := INFINITE
else begin
CurrentTime := ToInt64(GetTickCount());
if CurrentTime > TargetTime then
Result := 0
else begin
Result := TargetTime - CurrentTime;
if Result > TimeoutMSecs then
Result := 0; // GetTickCount rolled over
end;
end;
end;

{! We want to block most user input here but allow paint messages
to be processed and also non-client messages that relate to moving
or minimizing the window to be acted upon. Timer messages are also
processed! }
procedure ProcessPendingMessages;
var
Msg: TMsg;
const
NSCMask = $FFF0;
begin
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
case Msg.message of
WM_KEYFIRST..WM_KEYLAST, WM_MOUSEFIRST..WM_MOUSELAST: ; //
swallow
WM_NCMOUSEMOVE..WM_NCLBUTTONDBLCLK:
case Msg.wParam of
HTCAPTION, HTMINBUTTON: DispatchMessage(Msg);
end; {case}
WM_SYSCOMMAND:
case Msg.wParam and NSCMask of
SC_MINIMIZE, SC_RESTORE: DispatchMessage(Msg);
end; {case}
else
DispatchMessage(Msg);
end; {case}
end;

begin
EnsureSignalIsCreated;
if FCompleted then
Result := wrSignaled
else
if ProcessMessages then begin
TargetTime := ToInt64(GetTickCount()) + TimeoutMSecs;
H:= FSignal.Handle;
Result := wrAbandoned;
repeat
Ret := MsgWaitForMultipleObjectsEx(
1, H, TimeRemaining, QS_ALLINPUT, 0);
case Ret of
WAIT_ABANDONED : Exit;
WAIT_FAILED : Result := wrError;
WAIT_TIMEOUT : Result := wrTimeout;
WAIT_OBJECT_0 : Result := wrSignaled;
WAIT_OBJECT_0+1: ProcessPendingMessages;
end; {case }
until Result <> wrAbandoned;
end {if}
else
Result := FSignal.WaitFor(TimeoutMSecs);
end;


AND to not move to the next line while it is not completed. Since the
code is no prepared for working in parallel, specially due to the UI
update from the child thread. So I was thinking if I could keep the
MainThread doing almost nothing it would not cause conflict with the
child thread, and it would keep the reponsiveness to update the
progressbar, at least on the heaviest processing places.

Any Ideas?

Eduardo


--
Peter Below (TeamB)

Eduardo Elias

Posts: 319
Registered: 9/20/12
Re: How to move code to a child thread for the sake of having a UIshowing status
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 6, 2014 7:46 AM   in response to: Peter Below in response to: Peter Below
Peter,

Thank you for the answer.

I am not sure I was clear enought, or If I did not understand.

Like I said my problem is that the user UI is getting freeze due application
processing. Sure I have considered it before, but since I am using livebinding
a lot I am somewhat tied to the main thread.

But I was expecting that, besides this, Delphi would be generous to not freeze
the messaging loop.

That is not permiting me to make a progress bar (or ani indicator) run and
show the status that is working and give some feedback to the user.

I was wondering then: I cannot rewrite the application for background thread,
for the reason you said, my database and UI stuff is all tied to the main
thred. But what if I could keep my main thread quiet, while I move some part
of my code to run in a thread?

For example, I have the following:

Database.Connect;

That is part of the my regular flow of main thread. But takes sometimes 10
seconds.

I would like to do this:

ExecuteAndWait(Database.Connect);

That would move the execution to a background thread, but wait for its completion.
It is needed to wait since the code does not understand background operations.

This would give a chance for the message loop keep working and at least let
the UI alive and the progressbar working either.

I would not let anything else run, since it could conflict with the thread
being executed.

I was thinking that it could be a anonymous function, to preserve the context
of the main thread? I cannot use syncronize, doing so I will be back again
on the main thread and the message loop freeze to update progressbar.

What you think about that?

is it possible to run on Android either? (my project is cross platform, but
it is mainly windows based right now)

Eduardo

Eduardo Elias wrote:

[xe6 fmx windows]

I have wake up only now that i should have projected my code to move
processing code to thread and let my main thread responsive for UI
updates

That is not trivial at this point

Since I am using a lot of livebindings and it will make the controls
update. So I need to be on the MainThread.

I was wondering if there is a way to start a thread and wait it end
like:

ExecuteThreadAndWaititFinishes(<call to my actual code that opens
databases and cause controls to be updated>)

So my point here is to move all execution needed, where I know it is
heavy, to a child thread, only to keep the main thread free to update
the ui (and to update a progress bar on FMX)
The thread will have to do the UI updating via Synchronize usually (to
execute it in the main thread context).
That makes waiting for it to finish a bit complex, but it can be done.
However, whether it will actually give you a benefit depends on how
much of its real processing time the thread spends in fetching the
data
from the database and how much time the UI updates use.
There is an additional problem: database connections are usually tied
to the thread that created them. This depends on the database you
connect to and the connection components you use. So, executing a
query in a secondary thread and then using the retrieved data in the
main thread may be problematic, unless you can store the data into a
data structure of your own inside the thread first, and update the UI
from that data structure, not from the query component itself.

OK, now to answer your question: how you go about this depends on how
you want to design the thread. If it is to be a one action thread (you
create it, it executes its Execute method and exits that when the task
has completed, then you destroy the thread object) you can wait on the
thread's Handle directly. If the thread should be able to process
tasks whenever you have one for it to work on it would have a loop
inside Execute that waits for tasks to arrive, and signal completion
by means of a TSimpleEvent or similar object. In this case you would
wait on the handle of the event object.

The wait has to be done using the API function
MsgWaitForMultipleObjectsEx on Windows, which allows the wait to wake
up when a message to the waiting thread is received. I have no idea
how to do the equivalent on non-Windows platforms, sorry.

To show the principle i'll give you an example from my threading
library. The task object waits on an event in this case (FSignal is a
TSimpleEvent). You will not be able to directly use this code, of
course, but it should clearify the approach. The
ProcessPendingMessages procedure will also get Synchronized calls
processed, since those are triggered by a posted message.

If you want to use my threading library for your problem, go here
https://forums.embarcadero.com/thread.jspa?threadID=107478&tstart=0
and download the attached archive, it has the relevant units.

{! Wait for the call to complete. Optionally we can process a subset
of messages during the wait. That complicates the timeout handling,
though, since the wait can be interrupted by messages.}
function TAsyncCall.WaitForCompletion(TimeoutMSecs: Cardinal;
ProcessMessages: Boolean): TWaitResult;
var
TargetTime, CurrentTime: int64;
H: THandle;
Ret: DWORD;
function TimeRemaining: DWORD;
begin
if TimeoutMSecs = INFINITE then
Result := INFINITE
else begin
CurrentTime := ToInt64(GetTickCount());
if CurrentTime > TargetTime then
Result := 0
else begin
Result := TargetTime - CurrentTime;
if Result > TimeoutMSecs then
Result := 0; // GetTickCount rolled over
end;
end;
end;
{! We want to block most user input here but allow paint messages
to be processed and also non-client messages that relate to moving
or minimizing the window to be acted upon. Timer messages are also
processed! }
procedure ProcessPendingMessages;
var
Msg: TMsg;
const
NSCMask = $FFF0;
begin
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
case Msg.message of
WM_KEYFIRST..WM_KEYLAST, WM_MOUSEFIRST..WM_MOUSELAST: ; //
swallow
WM_NCMOUSEMOVE..WM_NCLBUTTONDBLCLK:
case Msg.wParam of
HTCAPTION, HTMINBUTTON: DispatchMessage(Msg);
end; {case}
WM_SYSCOMMAND:
case Msg.wParam and NSCMask of
SC_MINIMIZE, SC_RESTORE: DispatchMessage(Msg);
end; {case}
else
DispatchMessage(Msg);
end; {case}
end;
begin
EnsureSignalIsCreated;
if FCompleted then
Result := wrSignaled
else
if ProcessMessages then begin
TargetTime := ToInt64(GetTickCount()) + TimeoutMSecs;
H:= FSignal.Handle;
Result := wrAbandoned;
repeat
Ret := MsgWaitForMultipleObjectsEx(
1, H, TimeRemaining, QS_ALLINPUT, 0);
case Ret of
WAIT_ABANDONED : Exit;
WAIT_FAILED : Result := wrError;
WAIT_TIMEOUT : Result := wrTimeout;
WAIT_OBJECT_0 : Result := wrSignaled;
WAIT_OBJECT_0+1: ProcessPendingMessages;
end; {case }
until Result <> wrAbandoned;
end {if}
else
Result := FSignal.WaitFor(TimeoutMSecs);
end;
AND to not move to the next line while it is not completed. Since the
code is no prepared for working in parallel, specially due to the UI
update from the child thread. So I was thinking if I could keep the
MainThread doing almost nothing it would not cause conflict with the
child thread, and it would keep the reponsiveness to update the
progressbar, at least on the heaviest processing places.

Any Ideas?

Eduardo
Peter Below

Posts: 1,227
Registered: 12/16/99
Re: How to move code to a child thread for the sake of having a UIshowing status
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 6, 2014 10:55 AM   in response to: Eduardo Elias in response to: Eduardo Elias
Eduardo Elias wrote:

Peter,

Thank you for the answer.

I am not sure I was clear enought, or If I did not understand.

Like I said my problem is that the user UI is getting freeze due
application processing. Sure I have considered it before, but since I
am using livebinding a lot I am somewhat tied to the main thread.

But I was expecting that, besides this, Delphi would be generous to
not freeze the messaging loop.

You are doing that, not Delphi ;-). Any code in the main thread is
executed from a message that was retrieved from the message loop or
sent to a window when Application.ProcessMessage called the API
function PeekMessage. The code path will go on and block any further
processing of messages until it returns to the message loop. If you
want to get some UI control to repaint after a change you made to it
inside this lengthy code you have to call this:

procedure ProcessPaintrequests;
var
Msg: TMsg;
begin
while PeekMessage(Msg, 0, WM_PAINT, WM_PAINT, PM_REMOVE) do
DispatchMessage(Msg);
while PeekMessage(Msg, 0, WM_NULL, WM_NULL, PM_REMOVE) do
DispatchMessage(Msg);
end;

This basically runs a brief message loop to process any pending paint
messages. The second loop keeps Windows from thinking the application
is hung and from Windows ghosting to kick in.

But what if I could keep my main thread quiet, while I move some part
of my code to run in a thread?

You cannot just wait for something in the main thread, that would block
any message processing. If you run a loop until the background thread
is done you have to so it like this

while BackgroundProcessNotComplete do begin
Sleep(100);
ProcessPaintrequests;
CheckSynchronize;
end;

Without the Sleep the UI thread would consume excessive CPU resources
(basically one full core if you have several). Without the
CheckSynchronize calls to TThread.Synchronize would not be processed
and block the calling thread.

For example, I have the following:

Database.Connect;

That is part of the my regular flow of main thread. But takes
sometimes 10 seconds.

I would like to do this:

ExecuteAndWait(Database.Connect);

That would move the execution to a background thread, but wait for
its completion. It is needed to wait since the code does not
understand background operations.

With my AsyncTasksU unit this would take the form

var
LCall: IAsyncCall;
begin
LCall := Threadpool.BeginInvoke(
procedure // this will execute in the background thread
begin
Database.Connect;
end);
LCall.WaitForCompletion(INFINITE, true);
end;

The wait is done in a manner that allows the UI to repaint.

I was thinking that it could be a anonymous function, to preserve the
context of the main thread?

Executing something in a background thread is not the problem, waiting
for it to finish in the main thread is the problem <g>. The only
alternative to something like the above is to

- disable the main form
- lauch the background task
- return to the message loop (form will repaint, but the user cannot
do anything since the form is disabled)
- once the background task is done it calls a method via Synchronize
or post a message to the main form
to notify the main thread.
- in the method or message handler, enable the form again if all
tasks are done, otherwise launch the next
part of the processing using the same mechanism.

This works but is cumbersome to program (since you have no way to write
this as a sequential flow of instructions). It can also be difficult to
ensure that the main form is enabled again if the process runs into an
error and connot complete in the normal way.

is it possible to run on Android either? (my project is cross
platform, but it is mainly windows based right now)

As I said I have to pass on this, i'm a Windows only guy :-)


--
Peter Below (TeamB)

Steve Thackery

Posts: 151
Registered: 4/29/06
Re: How to move code to a child thread for the sake of having a UIshowing status
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 6, 2014 11:54 AM   in response to: Peter Below in response to: Peter Below
Peter, although it wasn't addressed to me, I just want to say a big
"thank you" for that post. Stuff like that is incredibly helpful and
you explained it very well.

--
SteveT
Dusten Scheere

Posts: 3
Registered: 7/23/08
Re: How to move code to a child thread for the sake of having a UIshowing status
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 7, 2014 7:31 AM   in response to: Steve Thackery in response to: Steve Thackery
Steve Thackery wrote:
Peter, although it wasn't addressed to me, I just want to say a big
"thank you" for that post. Stuff like that is incredibly helpful and
you explained it very well.

--
SteveT

I agree. Thank you so much Peter.
Eduardo Elias

Posts: 319
Registered: 9/20/12
Re: How to move code to a child thread for the sake of having aUIshowing status
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 7, 2014 9:06 AM   in response to: Peter Below in response to: Peter Below
Hey Peter,

Many thanks for your answer and time taken. Very instructive.

I will meditate on this and give some try.

Thank you.

Eduardo

Eduardo Elias wrote:

Peter,

Thank you for the answer.

I am not sure I was clear enought, or If I did not understand.

Like I said my problem is that the user UI is getting freeze due
application processing. Sure I have considered it before, but since I
am using livebinding a lot I am somewhat tied to the main thread.

But I was expecting that, besides this, Delphi would be generous to
not freeze the messaging loop.
You are doing that, not Delphi ;-). Any code in the main thread is
executed from a message that was retrieved from the message loop or
sent to a window when Application.ProcessMessage called the API
function PeekMessage. The code path will go on and block any further
processing of messages until it returns to the message loop. If you
want to get some UI control to repaint after a change you made to it
inside this lengthy code you have to call this:

procedure ProcessPaintrequests;
var
Msg: TMsg;
begin
while PeekMessage(Msg, 0, WM_PAINT, WM_PAINT, PM_REMOVE) do
DispatchMessage(Msg);
while PeekMessage(Msg, 0, WM_NULL, WM_NULL, PM_REMOVE) do
DispatchMessage(Msg);
end;
This basically runs a brief message loop to process any pending paint
messages. The second loop keeps Windows from thinking the application
is hung and from Windows ghosting to kick in.

But what if I could keep my main thread quiet, while I move some part
of my code to run in a thread?

You cannot just wait for something in the main thread, that would
block any message processing. If you run a loop until the background
thread is done you have to so it like this

while BackgroundProcessNotComplete do begin
Sleep(100);
ProcessPaintrequests;
CheckSynchronize;
end;
Without the Sleep the UI thread would consume excessive CPU resources
(basically one full core if you have several). Without the
CheckSynchronize calls to TThread.Synchronize would not be processed
and block the calling thread.

For example, I have the following:

Database.Connect;

That is part of the my regular flow of main thread. But takes
sometimes 10 seconds.

I would like to do this:

ExecuteAndWait(Database.Connect);

That would move the execution to a background thread, but wait for
its completion. It is needed to wait since the code does not
understand background operations.
With my AsyncTasksU unit this would take the form

var
LCall: IAsyncCall;
begin
LCall := Threadpool.BeginInvoke(
procedure // this will execute in the background thread
begin
Database.Connect;
end);
LCall.WaitForCompletion(INFINITE, true);
end;
The wait is done in a manner that allows the UI to repaint.

I was thinking that it could be a anonymous function, to preserve the
context of the main thread?
Executing something in a background thread is not the problem, waiting
for it to finish in the main thread is the problem <g>. The only
alternative to something like the above is to

- disable the main form
- lauch the background task
- return to the message loop (form will repaint, but the user cannot
do anything since the form is disabled)
- once the background task is done it calls a method via Synchronize
or post a message to the main form
to notify the main thread.
- in the method or message handler, enable the form again if all
tasks are done, otherwise launch the next
part of the processing using the same mechanism.
This works but is cumbersome to program (since you have no way to
write this as a sequential flow of instructions). It can also be
difficult to ensure that the main form is enabled again if the process
runs into an error and connot complete in the normal way.

is it possible to run on Android either? (my project is cross
platform, but it is mainly windows based right now)
As I said I have to pass on this, i'm a Windows only guy :-)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02