Board index » cppbuilder » Re: how to keep a thread alive without a CPU-hogging infinite loop

Re: how to keep a thread alive without a CPU-hogging infinite loop


2005-09-01 05:14:52 AM
cppbuilder52
"Chris Uzdavinis (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

The event handlers run in the main thread. They would call into your
thread object, which allocates a command object and inserts it into
the message queue. The thread wakes up and processes the message.

Thus, the event handler doesn't actually do the work. It simply gets
the process started.

The message queue can be "hidden" inside your thread object. So the
event handler can simply call a member function of your thread object
that actually does the allocation/insertion of the command object, all
behind the scenes.
OK, now I'm confused. The event handlers have to be members of the thread
where the component is. They need to use Synchronize to get anything to the
main thread. Even if there were some way to make a component in one thread
use an event handler in another thread, how would that other thread (my main
application thread in this case) then know which thread to send the command
back to? The event handler's parameters don't include an indication of
which thread initiated the event.
Then even dealing with commands that do start from the main thread, if it
simply called a member function of the thread to insert a command object
into the queue, how would that member function run? The thread is blocked
until it sees the object in the queue, so how can it be functioning to place
it's own wakeup call there?
 
 

Re:Re: how to keep a thread alive without a CPU-hogging infinite loop

In article <4314d475$ XXXX@XXXXX.COM >, XXXX@XXXXX.COM
says...
Quote
Ok, I've got something that sort of works, but not the way I'd like it to.
The thread has a socket connection, and one of the things it was waiting for
was communication on that socket. I rewrote it to use a blocking socket and
that takes care of that part, but at the expense of blocking out anything
else I wanted to happen. (For instance, now the main thread can't tell the
child thread to stop while the child thread is stuck waiting on that
blocking socket.) It worked much cleaner when I was using a non-blocking
socket and a
while (WaitingForResults) {
Application->ProcessMessages();
}
loop. With that setup I was able to wait for any of several different
things to happen, so the thread could do a lot more. Somehow the main
thread is able to handle this. How does Application->Run() manage to tell
the application's main thread to just sit there and react to any events that
occur? That's what I want the child thread to do as well - sit there and
react whenever an event occurs, but otherwise don't hog the CPU.


Lesley Anne



You can also use the following:
while (WaitingForResults){
Application->ProcessMessages();
SleepEx(1,true);
}
With SleepEx the thread goes to sleep for 1 ms and releases control to
other processes.
OR
you can send thread messages with
PostThreadMessage(m_WriteThread->ThreadID,myDOTHREAD_CLOSE,0,0);
and use the following code in the treads execute:
while((!Terminated)&&(l_boolEndThisThread==false))
{
if(PeekMessage(&msg,0,0,0,PM_REMOVE))
{ if(msg.hwnd != NULL)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}else
{
switch(msg.message){
case myDOTHREAD_CLOSE:
l_boolEndThisThread = true;
break;
// case :
// and so on
};//end of switch(msg.message)
}
}
SleepEx(1,true);
}
Hope this wil do better
 

Re:Re: how to keep a thread alive without a CPU-hogging infinite loop

"LesleyAnne" < XXXX@XXXXX.COM >writes:
Quote
OK, now I'm confused. The event handlers have to be members of the thread
where the component is.
Sorry. I was thinking that you were talking about GUI event handlers,
which must run in the main thread. Maybe I missed that you were using
some other type of event handler.
Quote
They need to use Synchronize to get anything to the main thread.
Yes, if they're running in the helper thread in the first place.
If you are somehow processing "events" in your worker thread already,
then you don't need a blocking message queue, since that's used for
communication between threads.
Quote
Even if there were some way to make a component in one thread use an
event handler in another thread,
There is such a way. That's what the message queue I described is for.
Quote
how would that other thread (my main application thread in this
case) then know which thread to send the command back to?
You could have a different message queue between each thread. Then
you know which thread you're talking to based on which message queue
you're using.
More typically, though, the main thread would tell the other threads
what to do, not the other way around (because the main thread isn't
waiting on a condition variable... it's processing the main
application event loop.)
Quote
The event handler's parameters don't include an indication of which
thread initiated the event.
What type of event handler are you talking about?
Quote
Then even dealing with commands that do start from the main thread, if it
simply called a member function of the thread to insert a command object
into the queue, how would that member function run?
When you say a "member function of the thread", that's somewhat
distorting reality. A thread isn't a class. It is a lightweight
process running in the same address of your application, with its own
stack frame and instruction pointer. A "thread object" is an attempt
to make an object LOOK like a thread, but really it simply is a normal
object that happens to also spawn a thread that runs a function that
is in that class. But OTHER threads can call member functions on this
thread-object, since it still is, afterall, just an object.
Quote
The thread is blocked until it sees the object in the queue, so how
can it be functioning to place it's own wakeup call there?
If you're using the message queue I posted, the push() function
signals the condition variable that the other thread is blocked upon.
That wakes up the sleeping thread, who then checks that the queue is
not empty (which it isn't), and so it breaks out of its wait-loop, and
dequeues the command and processes it. Once it is finished processing
that command, it calls pop() on the queue again, which blocks until
another message is available.
--
Chris (TeamB);
 

{smallsort}

Re:Re: how to keep a thread alive without a CPU-hogging infinite loop

Hans Zandbergen < XXXX@XXXXX.COM >writes:
Quote
You can also use the following:

while (WaitingForResults){
Application->ProcessMessages();
SleepEx(1,true);
}

With SleepEx the thread goes to sleep for 1 ms and releases control to
other processes.
Busy waiting is one of the least desirable solutions. Throwing a
sleep into the equation may solve or reduce the CPU problem, but it
introduces some pretty significant delays (in computer terms) between
when something needs to be handled and when it actually gets handled.
--
Chris (TeamB);
 

Re:Re: how to keep a thread alive without a CPU-hogging infinite loop

"Chris Uzdavinis (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

Yes, if they're running in the helper thread in the first place.

If you are somehow processing "events" in your worker thread
already, then you don't need a blocking message queue, since
that's used for communication between threads.
But I do need a blocking something. I need a way of saying: block this
thread until either an event occurs on a component in this thread or the
main thread calls one of this thread's functions.
The setup is one main thread that spawns multiple child threads (multiple
instances of the same TThread descendant class). Each child thread creates
its own TClientSocket to communicate with a remote machine. It should close
the connection and terminate either when the communication is finished or
when the main thread tells it to.
It sounds like I have a choice between:
(1) Make the TClientSocket a blocking socket, which allows the socket
connection to function but nothing else, so the main thread cannot
communicate with the child thread.
(2) Add in a blocking message queue, which would allow the main thread to
talk to the child thread, but sounds like it would block the ClientSocket,
which won't work.
or (3) don't use blocking in the child thread at all, which will allow both
the TClientSocket to work and also allow the parent thread to communicate
with it, but with no blocking it will take up 100% of available CPU time
just by continually checking the "while (WaitingForResults)" or "while
(!Terminated)" condition.
I've tried options (1) and (3), both of which work, but both of which have
drawbacks.
[Actually, option (1) has an additional drawback in that it's specific to a
TClientSocket only. I'd prefer a solution that would work more generically
on any non-visual component(s), but I don't know how to say "block until an
event occurs".]
 

Re:Re: how to keep a thread alive without a CPU-hogging infinite loop

"Hans Zandbergen" < XXXX@XXXXX.COM >wrote in
message news: XXXX@XXXXX.COM ...
Quote

you can send thread messages with

PostThreadMessage(m_WriteThread->ThreadID,myDOTHREAD_CLOSE,0,0);

and use the following code in the treads execute:

while((!Terminated)&&(l_boolEndThisThread==false))
{
if(PeekMessage(&msg,0,0,0,PM_REMOVE))
{ if(msg.hwnd != NULL)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}else
{
switch(msg.message){
case myDOTHREAD_CLOSE:
l_boolEndThisThread = true;
break;
// case :
// and so on
};//end of switch(msg.message)
}
}
SleepEx(1,true);
}

Hope this wil do better
Thanks. It looks like that might work.
There is one problem that I can't tell quite what some of the functions are
doing because my Builder6 help files don't contain any mention of
PostThreadMessage or PeekMessage, and there's only indirect references to
TranslateMessage and DispatchMessage in a couple of example pages, but no
explanation of them. Can anyone recommend a reference to how these (or
other) message functions work?
Ideally, I'd like a blocking version of PeekMessage, so that that SleepEx at
the end wouldn't be necessary. (At least it sure seems as though "wait
until there's a message to be processed, then process it" would be a
standard enough pattern for such a function to exist.)
 

Re:Re: how to keep a thread alive without a CPU-hogging infinite loop

"LesleyAnne" < XXXX@XXXXX.COM >writes:
Quote
It sounds like I have a choice between:
(1) Make the TClientSocket a blocking socket, which allows the socket
connection to function but nothing else, so the main thread cannot
communicate with the child thread.
(2) Add in a blocking message queue, which would allow the main thread to
talk to the child thread, but sounds like it would block the ClientSocket,
which won't work.
or (3) don't use blocking in the child thread at all, which will allow both
the TClientSocket to work and also allow the parent thread to communicate
with it, but with no blocking it will take up 100% of available CPU time
just by continually checking the "while (WaitingForResults)" or "while
(!Terminated)" condition.
I know how I would solve this using ACE, however, using TClientSocket
adds problems that I am not familiar with.
ACE has a "reactor" framework, which can basically implement exactly
what you want. Each thread could run its own reactor loop, which
basically waits until "somthing happens", with that something being
either I/O (in this case, socket activity), or an asychronous
notification, which would be an alternate way of "poking" the reactor
to wake up and invoke its notification.
On another question, why do you need threads to handle your network
connections in the first place? Why not just handle all the sockets
in the main thread?
--
Chris (TeamB);
 

Re:Re: how to keep a thread alive without a CPU-hogging infinite loop

"LesleyAnne" < XXXX@XXXXX.COM >wrote in message
Quote
Is there a simple way to keep a thread from reaching the end of its
Execute
function until conditions set in other functions are complete? I have a
threaded application where most of the child-thread processing is taking
place in various interrupt functions or functions called from the parent
thread and I want the Execute function to wait for everything to be
complete. I can make it work with a simple loop of the form:
[snip]
Quote
in which "WaitingForResults" is a thread-global boolean controlled in
other
functions. The only problem is that this keeps constant processing going
on
and uses 100% CPU for as long as the thread is active. Is there a better
way of doing this?
You could try the simple Sleep. Maybe:
while (WaitingForResults)
{
Sleep( 1000 );
}
HTH
Jonathan
 

Re:Re: how to keep a thread alive without a CPU-hogging infinite loop

LesleyAnne wrote:
Quote
But I do need a blocking something. I need a way of saying: block this
thread until either an event occurs on a component in this thread or the
main thread calls one of this thread's functions.
WaitForMultipleObjects() does this.
I don't know about VCL's TThread and TClientSocket, but with the
plain C versions, non-blocking communications use events which you can
wait on. You can also create your own events that the main thread can
signal to wake up the thread. The thread then waits for the
communications events as well as the main event. It processes
whichever event woke it up.
Quote
, but I don't know how to say "block until an
event occurs".]
WaitForSingleObject() or WaitForMultipleObjects()
 

Re:Re: how to keep a thread alive without a CPU-hogging infinite loop

"LesleyAnne" < XXXX@XXXXX.COM >wrote in message
Quote
"Hans Zandbergen" < XXXX@XXXXX.COM >wrote in
message news: XXXX@XXXXX.COM ...
>
>while((!Terminated)&&(l_boolEndThisThread==false))
>{
>if(PeekMessage(&msg,0,0,0,PM_REMOVE))
>{ if(msg.hwnd != NULL)
>{
>TranslateMessage(&msg);
>DispatchMessage(&msg);
>}else
>{
>switch(msg.message){
>case myDOTHREAD_CLOSE:
>l_boolEndThisThread = true;
>break;
>// case :
>// and so on
>};//end of switch(msg.message)
>}
>}
>SleepEx(1,true);
>}
>
>Hope this wil do better

Thanks. It looks like that might work.

There is one problem that I can't tell quite what some of the functions
are doing because my Builder6 help files don't contain any mention of
PostThreadMessage or PeekMessage, and there's only indirect references
to TranslateMessage and DispatchMessage in a couple of example pages,
but no explanation of them. Can anyone recommend a reference to how
these (or other) message functions work?

Ideally, I'd like a blocking version of PeekMessage, so that that SleepEx
at the end wouldn't be necessary. (At least it sure seems as though
"wait until there's a message to be processed, then process it" would be
a standard enough pattern for such a function to exist.)
OK, I'm not sure why my Builder6 help files didn't include this part, but I
found it in some help files left over from Builder5. It looks like this
should work, and I can replace the SleepEx at the end of that while loop
with a WaitMessage() at the beginning to avoid the sleep delay.
Either that or I may use the WaitForMultipleObjects() suggested in another
post. I'll try each and see which works best.