Board index » cppbuilder » Why is TMyThread not resumed?

Why is TMyThread not resumed?


2006-04-02 05:35:21 PM
cppbuilder91
Hello,
When a thread is created with the 'false' (resumed) argument then the
MySync() function is executed immediately. (see below)
When the thread is created with the 'true' (suspended) argument then the
MySync() function is NOT executed when followed by executing
pMyThread->Resume().
//It DOES start/resume immediately if using:
pMyThread->Resume();
while(true){
Application->ProcessMessages();
}
//It does NOT start/resume at all if using:
pMyThread->Resume();
while(true){
}
//It does NOT start/resume at all if using:
pMyThread->Resume()
Application->ProcessMessages();
while(true){
}
//Neither does it start/resume at all if changing priority:
Priority=tpHigher;
Is there something I'm missing?
====================
//my derived thread class
class TMyThread:public TThread{
//blabla
}
====================
//my thread creation
TMyThread* pMyThread=new TMyThread(true/false);
====================
//my thread execute() function
void __fastcall TMyThread::Execute(){
Synchronize(MySync);
}
====================
//my thread sync() function
void __fastcall TMyThread::MySync(void){
}
====================
Regards,
Henk
 
 

Re:Why is TMyThread not resumed?

I made a small mistake:
please read:
//It DOES/doesNOT start/resumeas
as:
//It DOES/doesNOT enter the MySync() function
If pMyThread->Resume() is executed the thread DOES always resume, it DOES
always execute the codeline 'Synchronize(MySync)' but it does NOT enter the
'MySync()' fcuntion.
Regards,
Henk
"Henk van Winkoop" < XXXX@XXXXX.COM >schreef in bericht
Quote
Hello,

When a thread is created with the 'false' (resumed) argument then the
MySync() function is executed immediately. (see below)
When the thread is created with the 'true' (suspended) argument then the
MySync() function is NOT executed when followed by executing
pMyThread->Resume().

//It DOES start/resume immediately if using:
pMyThread->Resume();
while(true){
Application->ProcessMessages();
}

//It does NOT start/resume at all if using:
pMyThread->Resume();
while(true){
}

//It does NOT start/resume at all if using:
pMyThread->Resume()
Application->ProcessMessages();
while(true){
}

//Neither does it start/resume at all if changing priority:
Priority=tpHigher;


Is there something I'm missing?


====================
//my derived thread class
class TMyThread:public TThread{
//blabla
}
====================
//my thread creation
TMyThread* pMyThread=new TMyThread(true/false);
====================
//my thread execute() function
void __fastcall TMyThread::Execute(){
Synchronize(MySync);
}
====================
//my thread sync() function
void __fastcall TMyThread::MySync(void){
}
====================

Regards,

Henk


 

Re:Why is TMyThread not resumed?

"Henk van Winkoop" < XXXX@XXXXX.COM >wrote in message
Quote
If pMyThread->Resume() is executed the thread DOES always
resume, it DOES always execute the codeline 'Synchronize(MySync)'
but it does NOT enter the 'MySync()' fcuntion.
Synchronize() requires the main thread to process new messages, because
Synchronize() posts a message to the queue. Your loop that does not work is
not calling Application->ProcessMessages(). If the loop is in the main
thread, then you must call ProcessMessages() inside your loop. The code is
that calling ProcessMessages() before entering the loop is likely calling it
before the thread calls Synchronize(), so the message is still ignored.
Gambit
 

{smallsort}

Re:Why is TMyThread not resumed?

@Gambit,
Quote
Synchronize() requires the main thread to process new messages, because
Synchronize() posts a message to the queue.
So somewhere I need to place ProcessMessages()?
Quote
Your loop that does not work is
not calling Application->ProcessMessages().
Allright
Quote
If the loop is in the main
thread, then you must call ProcessMessages() inside your loop.
It is not, so...
Quote
The code is
that calling ProcessMessages() before entering the loop is likely calling
it
before the thread calls Synchronize(), so the message is still ignored.
????
...what do I need?
This was my situation:
MyMainForm->MyOtherObject->MyThread()
I thought I red somewhere that threads must be directly under the
mainapplication so I
rewrote my application (took 8 hours...) using callbacks and window messages
to get the thread as follows:
MyMainForm->MyThread()
but...saddly...the same problem occured...snif......
One of my MyMainForm functions:
- resets an event
- resumes MyThread
- waits for that event to be signalled (WaitForSingleObject)
Just before MyThread suspends itself, it sends a message to MyMainForm.
MyMainForm messagehandler then sets/signals the above event.
So I expect that my WaitForSingleObject will carry on.
The 'WaitForSingleObject' line code causes MyThreat to not go into the
Synchonize argument function.
If I remove this code line then Synchronize runs into it's argument
function!
Can you tell me where exactly I have to put what kind of code to solve my
problem? (please...)
Regards,
Henk
 

Re:Why is TMyThread not resumed?

"Henk van Winkoop" < XXXX@XXXXX.COM >wrote in message
Quote
>If the loop is in the main
>thread, then you must call ProcessMessages() inside your loop.
It is not, so...
If your loop is NOT in the main thread, then DO NOT call ProcessMessages()
inside the loop at all. ProcessMessages() is not thread-safe, and cannot
safely be call outside the context of the main thread. Your problem is
elsewhere.
Quote
...what do I need?
There is no way to know that without first knowing more about what you are
trying to do to begin with. What does your thread actually do? What does
your loop actually do, and where is it called from exactly?
Quote
This was my situation:
MyMainForm->MyOtherObject->MyThread()
Then MyOtherObject does actually exist in the main thread, not its own
worker thread. If the loop is inside of MyOtherObject, then the loop is
likely being called in the context of the main thread afterall. Please show
a more complete code snippet.
Quote
One of my MyMainForm functions:
- resets an event
- resumes MyThread
- waits for that event to be signalled (WaitForSingleObject)
Ok so far.
Quote
Just before MyThread suspends itself, it sends a message to MyMainForm.
How, exactly?
Quote
MyMainForm messagehandler then sets/signals the above event.
Why not just have the thread signal the event directly?
Quote
So I expect that my WaitForSingleObject will carry on.
If the main thread is blocked because of your loop, then there are no
messages being processed, and thus the thread's message is not being
received in order to signal the event. Again, please show an actual code
snippet that shows exactly what you are doing.
Quote
The 'WaitForSingleObject' line code causes MyThreat to not go
into the Synchonize argument function.
WaitForSingleObject() is a blocking function. It does not process the
message queue at all. If you need to do a blocking wait while still
processing messages, then you have to call WaitForSingleObject() in a loop,
specifying a timeout so that the waiting exits periodically so that you can
pump the queue in between iteration of the loop.
Quote
If I remove this code line then Synchronize runs into it's argument
function!
All the more reason to suspect that you are blocking the main thread from
processing new messages while you are waiting for the event to be signalled.
Quote
Can you tell me where exactly I have to put what kind of code to
solve my problem?
No, because you haven't shown any of your actual code to begin with.
Gambit
 

Re:Why is TMyThread not resumed?

@Gambit,
Thanks for your time and remarks.
Quote

>Just before MyThread suspends itself, it sends a message to MyMainForm.

How, exactly?

I handover a 'MyMainForm_Pointer' to MyThread by a thread constructor
argument.
Then inside the thread I use;
PostMessage(MyMainForm_Pointer->Handle,MY_MSG_TYPE,0);
This message just works fine.
Quote

Why not just have the thread signal the event directly?

Because the signal-event (CreateEvent(MyEvent)) is declared in MyMainForm.
To signal it from within MyThread I need a handle to MyEvent inside
MyThread. (I think...)
So another MyThread constructor argument would do but I thought lets try it
with a message.
As WaitForSingleObject blocks execution of the Synchronize()-argument
function it does not matter directly signalling MyEvent or doing it by a
message from inside the argument-function because the argument-function will
never be executed.
What eventually could be the advantage of directly resetting MyEvent over
using messages to do so?
Quote

If the main thread is blocked because of your loop, then there are no
messages being processed, and thus the thread's message is not being
received in order to signal the event.
WaitForSingleObject() is a blocking function. It does not process the
message queue at all.
Thats the crux I did not know!
I solved it by:
//test each 1ms if event is signalled
while((dwRes=WaitForSingleObject(pMyEvent,1))==WAIT_TIMEOUT){
Application->ProcessMessages()
}
Although it's not a nice solution then an endless timeout is not detected
because now WAIT_TIMEOUT is used in a
tricky way.
There must be some more reliable method.
============================================================
I'm working on an application that communicates with a small Robot (Asuro)
by infrared signals through the comport. The comport object uses 4 events
with WaitForMultipleObjects to control WriteFile() and ReadFile()
operations. This all works fine.
I need the comport object to exchange data through 'shared resources' with
the rest of my application.
My first idea was to not have to worry about data overflows
sending/receiving data to/from the comport. So I figgered out that using
ringbuffers with underrun/overflow detection would do best.
My application (user-object) sends tx-data, byte by byte, to the
tx-ringbuffer which in turn is read by the comport-object to be transmitted
using WriteFile(). The same accounts for receiving infrared data, namely the
comport-object reads received data by ReadFile() and puts each received
character into the rx-ringbuffer. A low level thread then reads the
rx-ringbuffer.
To not get atomic errors I use 4 ringbuffer threads with mutexes:
1. a tx-ringbuffer-write-thread
2. a tx-ringbuffer-read-thread
3. a rx-ringbuffer-write-thread
4. a rx-ringbuffer-read-thread
both tx-threads use a tx-mutex
both rx-threads use a rx-mutex
(I first used two same ringbuffer-objects (tx and rx) from the same
ringbuffer class but debugging got very confusing as the de{*word*81} accesses
the ringbuffer sourcecode without knowing if its the tx- or rx- ringbuffer
now debugging....so during development I use two equally ringbuffer (tx and
rx) classes)
The function of the threads is to exchange characters between user-object or
comport-object and both ringbuffers. The only thing I would like to worry
about is putting characters into the tx-ringbuffer and read characters from
the rx-ringbuffer.
Using mutexes, for example, if no tx-ringbuffer-write nor tx-ringbuffer-read
operation is in process then both corresponding tx-threads
WaitForSingleObject(Mutex,Delay) functions will continuously being
signalled. Therefore I let all threads suspend itself to not spill
processortime. Reading/writing ringbuffer operations always starts with a
thread-resume.
If I want a character to be transmitted by the comport, the user-object:
- stores the transmit character into a tx-ringbuffer-write-thread variable
- resumes the tx-ringbuffer-write-thread (which through the comport-object
resumes the tx-ringbuffer-read thread)
Now I would like the program to wait, using no processortime, until the
tx-character really has been written into the tx-ringbuffer by the comport
object. Therefore I thought to use a WaitForSingleObject function to wait
for a signal from the tx-ringbuffer-write-thread that writing has been
finished. The tx-ringbuffer-write-thread signals this event just prior to
suspending itself.
So in short:
Tx:
1. the user-object writes a tx-character into tx-ringbuffer
2. the comport-object reads a tx-character from ringbuffer, then transmits
it by WriteFile()
Rx:
3. the comport-object receives a rx-character by ReadFile(), then writes it
into rx-ringbuffer
4. the user-object reads a rx-character from rx-ringbuffer
I saw programs that POLL the comport-object. Maybe my approach according the
comport is not such a good idea...
But again, ideas are welcome.
Regards,
Henk
 

Re:Why is TMyThread not resumed?

"Henk van Winkoop" < XXXX@XXXXX.COM >wrote in message
Quote
I handover a 'MyMainForm_Pointer' to MyThread by a
thread constructor argument. Then inside the thread I use;
PostMessage(MyMainForm_Pointer->Handle,MY_MSG_TYPE,0);
The TWinControl::Handle property is not thread-safe. The code above works
only when the VCL is not in the middle of re-creating the TForm's HWND
window. If it is, then your code above will not work, and worse it can
screw up the VCL very badly. When the Handle property is accessed, if the
HWND has not been allocated yet then it is allocated at that moment. The
calling thread becomes the owner of the window. If the worker thread
manages to access the Handle propety before the main thread has finished
allocating the new HWND, then the worker thread, not the main thread, will
become the owner of the hew window. That is very bad.
I would suggest that you NOT access the Handle directly in your worker
thread. Either pass just the HWND itself instead of the entire TForm
pointer (and then update the HWND whenever the TForm recreates it), or else
use the thread's Synchronize() method to access the Handle property in a
thread-safe manner (in which case, you don't need the PostMessage() at all).
Quote
>Why not just have the thread signal the event directly?

Because the signal-event (CreateEvent(MyEvent)) is declared in MyMainForm.
So? You can have the TForm pass the HANDLE of the event to the thread, or
you can give the event a name and the thread can call OpenEvent(). Either
way, the thread can then call Reset/Pulse/SetEvent() instead of
PostMessage() when needed.
Quote
To signal it from within MyThread I need a handle to MyEvent inside
MyThread. (I think...)
Yes. Which is very easy to set up.
Quote
So another MyThread constructor argument would do but I thought
lets try it with a message.
You are not accessing the TForm's HWND safely to begin with, so your message
approach is not very good. IT can be made to be safe, but that will require
some extra coding on your part.
Quote
As WaitForSingleObject blocks execution of the Synchronize()-argument
function it does not matter directly signalling MyEvent or doing it by a
message
from inside the argument-function because the argument-function will never
be executed.
Yes, it does matter. You can have the thread signal the event directly
without using Synchronize() at all, and no messages will be involved at all,
either. Just because an event was created by the main thread does NOT mean
that the main thread is the only thread that can signal it. Any thread can.
WaitForSingleObject() will wake up immediately regardless of which thread is
signalling the event. You do not have that option if you use messages.
Quote
What eventually could be the advantage of directly resetting MyEvent over
using messages to do so?
It is thread-safe, and much more efficient in general. Events are
specifically designed with multi-threaded scenerios in mind.
Quote
I solved it by:

//test each 1ms if event is signalled
while((dwRes=WaitForSingleObject(pMyEvent,1))==WAIT_TIMEOUT){
Application->ProcessMessages()
}
If you are going to do that, then I HIGHLY suggest that you increase the
timeout to at least 100. Calling ProcessMessage() at 1 millsecond intervals
is going to peg your CPU usage, slowing down the entire machine.
Quote
There must be some more reliable method.
There is - get rid of the message altogether and let the worker thread
operate on the event object directly.
Gambit
 

Re:Why is TMyThread not resumed?

Quote

>There must be some more reliable method.

There is - get rid of the message altogether and let the worker thread
operate on the event object directly.


Hello Gambit,
I followed your advise.
the 'Synchronize' problem is over, but the next appears....
The WaitForSingleObject( h_thread_writing_finished_event ) function
sometimes is not signalled.
My Resume() and WFSO() functions are in a callback function that is called
from a communication thread...
//---WRITE-THREAD-CONSTRUCTOR---//
__fastcall TMyWriteThread::TMyThread(
bool CreateSuspended,
TMyReadWriteMutex p_read_write_mutex,
HANDLE h_thread_writing_finished_event
){
Fp_read_write_mutex = p_read_write_mutex;
Fh_thread_writing_finished_event = h_thread_writing_finished_event
Priority = tpNormal;
.............
}
//---WRITE-THREAD-EXECUTE---//
void __fastcall TMyWriteThread::Execute(){
while ( !Terminated ){
Synchronize ( f_do_write_character );
Suspend();
}
}
//---WRITE-THREAD-SYNCHRONIZED-FUNCTION---//
void __fastcall TMyWriteThreadr::f_do_write_character(void){
WaitForSingleObject ( Fp_read_write_mutex, 15000 );
f_write_single_char_into_ringbuffer(char ...);
ReleaseMutex ( Fp_read_write_mutex );
SetEvent ( Fh_thread_writing_finished_event );
}
//
//The read-function-thread is an exact copy of the write-function-thread,
only
// f_write_single_char_into_ringbuffer(char ...);
//is replaced by
// f_read_single_char_from_ringbuffer(char* ...);
//and
// Fh_thread_reading_finished_event
//is replaced by
// Fh_thread_writing_finished_event
//
//---CALLBACK-(WRITE)-FUNCTION-CALLED-FROM-COMMUNICATION-THREAD---//
bool __fastcall TMainForm::CallbackWriteFunction(char c_write_character){
ResetEvent( h_thread_writing_finished_event );
MyWriteThread->Resume();
while ( WaitForSingleObject( h_thread_writing_finished_event , 100 ) ==
WAIT_TIMEOUT ){
Application->ProcessMessages();
}
//wait for thread to suspend (avoiding eventually resuming resumed thread)
//as happens when transmitting multiple characters
while ( !MyWriteThread->Suspended){
Application->ProcessMessages();
}
return true/false;
}
Sometimes the program hangs in the WaitForSingleObject(
h_thread_writing_finished_event ) loop.
Regards
Henk
 

Re:Why is TMyThread not resumed?

"Henk van Winkoop" < XXXX@XXXXX.COM >wrote in message
Quote
The WaitForSingleObject( h_thread_writing_finished_event )
function sometimes is not signalled.
Then your thread is not signalling the event properly.
Quote
__fastcall TMyWriteThread::TMyThread(
bool CreateSuspended,
TMyReadWriteMutex p_read_write_mutex,
HANDLE h_thread_writing_finished_event
){
Fp_read_write_mutex = p_read_write_mutex;
Fh_thread_writing_finished_event = h_thread_writing_finished_event
Priority = tpNormal;
.............
}
I do not see you calling the TThread base class constructor anywhere.
Please always post code AS-IS.
Also, I strongly recommend that you get rid of the CreateSuspended parameter
altogether. Your constructor is initialing members of the thread class, so
you shold never be setting CreateSuspended to false. So you can hard-code
the parameter to true when calling the base class TThread constructor.
Quote
void __fastcall TMyWriteThread::Execute(){
while ( !Terminated ){
Synchronize ( f_do_write_character );
Suspend();
}
}
Why are you performing *all* of the thread's work in the context of the main
thread? You are completely defeating the purpose of using a thread in the
first place. You should be using Synchronize() only to access the GUI and
thread-unsafe resources. Not to perform the thread's main work.
Also, your Application->ProcessMessages() loops are not very efficient in
general. You should call ProcessMessages() only when there are actual
messages available to process. You can use MsgWaitForMultipleObjects()
instead of WaitForSingleObject() for that.
Try this code instead:
__fastcall TMyWriteThread::TMyWriteThread(HANDLE h_read_write_mutex,
HANDLE h_thread_writing_finished_event)
: TThread(true)
{
Priority = tpNormal;
Fh_read_write_mutex = h_read_write_mutex;
Fh_thread_writing_finished_event = h_thread_writing_finished_event
// ...
}
void __fastcall TMyWriteThread::Execute()
{
while( !Terminated )
{
switch( WaitForSingleObject(Fh_read_write_mutex, 100) )
{
case WAIT_OBJECT_0:
f_write_single_char_into_ringbuffer(...);
ReleaseMutex(Fh_read_write_mutex);
SetEvent(Fh_thread_writing_finished_event);
Suspend();
break;
case WAIT_ABANDONED:
Terminate();
break;
}
}
}
bool __fastcall TMainForm::CallbackWriteFunction(char c_write_character)
{
ResetEvent(h_thread_writing_finished_event);
MyWriteThread->Resume();
bool KeepLooping = true;
do
{
switch( MsgWaitForMultipleObjects(1,
&h_thread_writing_finished_event, FALSE, 100, QS_ALLINPUT) )
{
case WAIT_OBJECT_0:
case WAIT_ABANDONED_0:
KeepLooping = false;
break;
case WAIT_OBJECT_0+1:
Application->ProcessMessages();
break;
}
}
while( KeepLooping );
while( !MyWriteThread->Suspended )
Application->ProcessMessages();
return true;
}
Now, with all of that said, why are you using a writing thread at all? Your
buffering code is effectively blocking the callback function anyway, so why
not just store the data into the buffer directly in the callback itself and
get rid of the thread altogether?
bool __fastcall TMainForm::CallbackWriteFunction(char c_write_character)
{
bool KeepLooping = true;
do
{
switch( MsgWaitForMultipleObjects(1, &h_read_write_mutex, FALSE,
100, QS_ALLINPUT) )
{
case WAIT_OBJECT_0:
write_single_char_into_ringbuffer(c_write_character);
ReleaseMutex(h_read_write_mutex);
KeepLooping = false;
break;
case WAIT_OBJECT_0+1:
Application->ProcessMessages();
break;
case WAIT_ABANDONED_0:
KeepLooping = false;
break;
}
}
while( KeepLooping );
return true;
}
Gambit
 

Re:Why is TMyThread not resumed?

Hello Gambit,
========================================
Quote
>The WaitForSingleObject( h_thread_writing_finished_event )
>function sometimes is not signalled.

Then your thread is not signalling the event properly.
Okay.
========================================
Quote
>__fastcall TMyWriteThread::TMyThread(
>.............
>}

I do not see you calling the TThread base class constructor anywhere.
In the original program it is there.
"):TThread(CreateSuspended){"
========================================
Quote
Please always post code AS-IS.
I will.
========================================
Quote
Also, I strongly recommend that you get rid of the CreateSuspended
parameter
altogether. Your constructor is initialing members of the thread class, so
you shold never be setting CreateSuspended to false. So you can hard-code
the parameter to true when calling the base class TThread constructor.
I never realized it could (old habbits...)
========================================
Quote
void __fastcall TMyWriteThread::Execute(){
while ( !Terminated ){
Synchronize ( f_do_write_character );
Suspend();
}
}
Why are you performing *all* of the thread's work in the context of the
main
thread?
I read the very very very good book (never seen a better teaching one)
Teach Yourself C++ Builder in 21 Days many times but there's nothing
about using threads. So I got the info from the helpfiles.
========================================
Quote
You are completely defeating the purpose of using a thread in the
first place. You should be using Synchronize() only to access the GUI and
thread-unsafe resources. Not to perform the thread's main work.
As I did not find any thread documentation I started experimenting with
threads.
Below is a document I wrote literally (for myself) a few years ago.
Giving a thread a priority above normal like 'tpHigher' and using a 'while'
loop
and not using the 'Synchronize' function, will NOT return control to the cal
ling
application.
Using the 'Synchronize' function inside the 'while' loop DOES return control
to
the calling application.
In some way, 'Synchronize' takes care that unless Thread has a higher
priority,
other windows interrupts are enabled to do their tasks. I think it has to do
with timesharing which is absolutely disabled when not using the
'Synchronize'
function.
So somewhere this info was baked in my mind. That is why I always put all my
thread code inside 'Synchronize'... ;-)
========================================
Quote
Also, your Application->ProcessMessages() loops are not very efficient in
general. You should call ProcessMessages() only when there are actual
messages available to process. You can use MsgWaitForMultipleObjects()
instead of WaitForSingleObject() for that.
I will study this 'MsgWaitForMultipleObjects()'.
========================================
Quote
Now, with all of that said, why are you using a writing thread at all?
Your
buffering code is effectively blocking the callback function anyway, so why
not just store the data into the buffer directly in the callback itself and
get rid of the thread altogether?
I looked for mutexes at MSDN and this is what I found:
"For example, to prevent two threads from writing to shared memory
at the same time, each thread waits for ownership of a mutex object
before executing the code that accesses the memory. After writing
to the shared memory, the thread releases the mutex object."
So I assumed that access through mutexes always requires using threads.
========================================
At last .....
I used your code (without threads) to write/read into/from the
tx-ringbuffer.
I now use 3 callback functions:
- writing single character to ringbuffer
- reading single character from ringbuffer
- checking for non-empty ringbuffer, to re-signal the comport reading event
after each write operation.
Result:
AS SOLID AS A ROCK!
The program sends all tx-ringbuffer written characters without{*word*154} or
loosing any character.
I've learned a lot.
Thanks for your support.
Regards,
Henk
 

Re:Why is TMyThread not resumed?

"Henk van Winkoop" < XXXX@XXXXX.COM >wrote in message
Quote
>Also, I strongly recommend that you get rid of the CreateSuspended
parameter
>altogether. Your constructor is initialing members of the thread class,
so
>you shold never be setting CreateSuspended to false. So you can
hard-code
>the parameter to true when calling the base class TThread constructor.

I never realized it could (old habbits...)
You never said which version of BCB you are actually using. In versions
prior to BCB 6, the thread's Execute() method begins running immediately
when CreateSuspended is false - BEFORE the constructor finishes running!
This can lead to problems with Execute() accessing members that have not
been initialized yet.
This was finally fixed in BCB 6, but since I don't know which version you
are actually using, I aired on the cautious side.
Quote
As I did not find any thread documentation I started experimenting
with threads. Below is a document I wrote literally (for myself) a
few years ago.
That document is a little misleading in this situation.
The use of Synchronize() has nothing to do with the thread's priority. A
thread that has a priority of tpNormal can still use a while() loop to block
the program's other threads just as easily. Allowing other threads to run
has to do with a given thread's ability to relinquish its CPU time slices so
that other pending threads can then access the CPU for their own work. If a
thread does not relinquish its time slices, such as in a loop that does not
call any system calls that force relinquishing, then it becomes the only
thread in the process that can access the CPU, and the other threads become
starved for attention. Sleep() and WaitFor...() are examples of system
functions that release a thread's remaining time slices. A simple
workaround for a tight loop to not starve other threads is to have the loop
call Sleep(0) periodically.
Quote
In some way, 'Synchronize' takes care that unless Thread has a
higher priority, other windows interrupts are enabled to do their tasks.
Synchronize() doesn't care about priority at all. The only reason that
Synchronize() is allowing other threads (the main thread in this situation)
to run is because Synchronize() puts the calling thread into a waiting
state. Regardless of the thread's priority, the thread is blocked.
Internally, Synchronize() allocates an event object for each method that is
passed to it, and then uses WaitForSingleObject() to wait for the main
thread to signal those events indicating that the methods have been called.
During that waiting, the calling thread relinquishes its remaining CPU time
slices so that other threads can use the CPU.
Quote
That is why I always put all my thread code inside 'Synchronize'... ;-)
That is a VERY bad design for threads. Like I said, you are forcing the
main thread to do all of the actual work, which is a complete waste of
threads in general. The whole purpose of using thread at all is to run
multiple blocks of code in parallel with each other. Synchronize() forces
the specified methds to be serialized instead since everything goes through
the main thread, which can only do one thing at a time. That is why
Synchronize() should only be used for GUI operations (which must always go
through the main thread) and thread-unsafe operations (those that access
resources that are not protected from multi-threaded accesses via
system-provided synchronization objects, such as mutexes, semaphores,
critical sections, etc). Everything else should NOT be done inside of
Synchronize().
Quote
I looked for mutexes at MSDN and this is what I found:

"For example, to prevent two threads from writing to shared memory
at the same time, each thread waits for ownership of a mutex object
before executing the code that accesses the memory. After writing
to the shared memory, the thread releases the mutex object."

So I assumed that access through mutexes always requires using threads.
You are not taking into account that the main thread is itself a thread like
any other, just one that is started by the OS itself instead of your own
code. But it is still a thread nontheless, and can participant in mutexes,
and other synchronization objects, like any other thread.
Quote
I used your code (without threads) to write/read into/from the
tx-ringbuffer.
If the callbacks themselves are always executed in the context of the main
thread, then they are already serialized, and thus no extra threading is
needed at all. But you haven't provided any details about what exactly is
calling the callbacks, so I can't say that for sure. But in any case, even
if the callbacks are being called by other threads, your use of a mutex to
protect access to the ring buffer itself is enough to ensure safe
operations, so you didn't need to use extra threads to begin with.
Gambit
 

Re:Why is TMyThread not resumed?

"Remy Lebeau \(TeamB\)" < XXXX@XXXXX.COM >writes:
Quote
If a thread does not relinquish its time slices, such as in a loop
that does not call any system calls that force relinquishing, then
it becomes the only thread in the process that can access the CPU,
and the other threads become starved for attention. Sleep() and
I have trouble believing this. For windows 3.1 it was true, because
the multi-threading was cooperative, but since windows NT, the
scheduler has been pre-emptive. Threads are assigned a quanta that is
managed by the os, and whether they yield or not, when that quanta is
used up the other threads may get scheduled. A Sleep of (0) will
PREMATURELY yield the time slice, but should not be required.
The thread priorities have to do with "who gets scheduled next" and
how big their quanta. A high-priority thread can starve a
lower-priority thread, but two threads with equal priority should both
be scheduled on a 1-CPU computer, even if they're both CPU-bound.
(It may get choppy, but neither process should be completely starved.)
--
Chris (TeamB);
 

Re:Why is TMyThread not resumed?

"Chris Uzdavinis (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote
I have trouble believing this. For windows 3.1 it was true, because
the multi-threading was cooperative, but since windows NT, the
scheduler has been pre-emptive. Threads are assigned a quanta that is
managed by the os, and whether they yield or not, when that quanta is
used up the other threads may get scheduled. A Sleep of (0) will
PREMATURELY yield the time slice, but should not be required.
Then why are threads that run tight unyielding loops able to peg the CPU and
starve other threads of equal priority?
Gambit