Board index » delphi » Main Thread reaction to TThread.Synchronize()

Main Thread reaction to TThread.Synchronize()

I have been wondering about the real workings of TThread.Synchronize():
According to my understanding, this function switches the execution of the
specified procedure from the calling thread to the main thread.

Assuming this is correct, my question is two-fold:

(1) How is the scheduling of the Main thread affected, i.e. if the Main
Thread
is already busy executing a(nother) procedure, will it switch immediately
to
execute the Synchronize()'d procedure or will it complete its current
business first?

(2) If Main thread does switch immediately to execute the Synchronize()'d
procedure, abandoning execution of its current task, how can then
Synchronize() guarantee the safety of VCL components?
For example, if the Main thread is updating the X property of a Y
component,
and then another thread wants to change the same Y.X property, using
Synchronize(), how is a collision avoided?

In my own components, I have applied mutexes to all major write access
methods
so that updates are forced to be completed one by one. However if
Synchronize()
is used to access my components, the effect is undermined because then all
calls
are made from the same (Main) thread, so Mutex doesn't help.

Your answers are much appreciated

Kristofer Skaug
kristo...@skaug.demon.nl

 

Re:Main Thread reaction to TThread.Synchronize()


Quote
Kristofer Skaug wrote in message

<01bdcf44$47393860$ede7a...@skaug.demon.nl>...

Quote
>I have been wondering about the real workings of TThread.Synchronize():
>According to my understanding, this function switches the execution of the
>specified procedure from the calling thread to the main thread.
>(1) How is the scheduling of the Main thread affected, i.e. if the Main
>Thread
>is already busy executing a(nother) procedure, will it switch immediately
>to
>execute the Synchronize()'d procedure or will it complete its current
>business first?

The main thread will finish its current business first. The synchronized
function will be called when the main thread enters the message loop. This
is also the case when the main thread calls Application.ProcessMessages.

Quote
>(2) If Main thread does switch immediately to execute the Synchronize()'d
>procedure, abandoning execution of its current task, how can then
>Synchronize() guarantee the safety of VCL components?
>For example, if the Main thread is updating the X property of a Y
>component,
>and then another thread wants to change the same Y.X property, using
>Synchronize(), how is a collision avoided?

That's the main reason. Not only the VCL, but everything in Windows would be
in danger. And, for a moment, think what happens in a multi-processor
system...

Quote
>In my own components, I have applied mutexes to all major write access
>methods
>so that updates are forced to be completed one by one. However if
>Synchronize()
>is used to access my components, the effect is undermined because then all
>calls
>are made from the same (Main) thread, so Mutex doesn't help.

That's right.
But if you request the mutex _before_ you synchronize, you'll get the
desired behavior. Note that mutexes work system wide. So you do achieve that
two instances of your program cannot update at the same time. If you don't
need this, use critical sections, which have less overhead but serve the
purpose you describe.

--
Zweitze de Vries
Zweitze.at.iname.com
When replying, please adjust return address

Re:Main Thread reaction to TThread.Synchronize()


In article <903991260.29123.2.rover.c29fe...@news.demon.nl>, "Zweitze de
Vries" <zweitze.at.iname.com> ("Zweitze de Vries" <zweitze.at.iname.com>)
says...

Quote
> The main thread will finish its current business first. The synchronized
> function will be called when the main thread enters the message loop. This
> is also the case when the main thread calls Application.ProcessMessages.

Actually, no. At least not in Delphi 3. The TThread.Synchronize method
uses SendMessage. SendMessage immediately calls the WndProc of the given
window, and does not return until processing of the message is done.

The handler for CM_EXECPROC simply calls the desired function directly.

M.

--
Ettertraktet kaffe, er det ekstra god kaffe?
mailto:martin.lars...@delfidata.no.NOSPAM
http://www.delfidata.no/users/~martin

Re:Main Thread reaction to TThread.Synchronize()


On Mon, 24 Aug 1998 23:51:00 +0200, martin.lars...@delfidata.no.NOSPAM

Quote
(Martin Larsson) wrote:
>In article <903991260.29123.2.rover.c29fe...@news.demon.nl>, "Zweitze de
>Vries" <zweitze.at.iname.com> ("Zweitze de Vries" <zweitze.at.iname.com>)
>says...
>> The main thread will finish its current business first. The synchronized
>> function will be called when the main thread enters the message loop. This
>> is also the case when the main thread calls Application.ProcessMessages.

>Actually, no. At least not in Delphi 3. The TThread.Synchronize method
>uses SendMessage. SendMessage immediately calls the WndProc of the given
>window, and does not return until processing of the message is done.

Only within the same thread.  When you send a message to another thread,
it doesn't get delivered until the receiving thread retrieves messages.

Quote
>The handler for CM_EXECPROC simply calls the desired function directly.

>M.

--
Report all {*word*201} mail to your Potsmaster.

Re:Main Thread reaction to TThread.Synchronize()


I appreciate you guys helping me out, but...
Hmmm... now I am really confused.
The programming problem which lead up to my question was the following:

- I have a Delphi app which uses a C++ DLL which handles blocking TCP/IP
sockets to communicate with an external slave unit. For example, when
I use a DLL function call SendCommandString(pCommand,pResponse), the
command contained in the PChar pCommand is sent out over the socket and
the DLL holds out until an ASCII response string is received from the other
side
(with a certain timeout, of course). Now the intention is that no other
commands
shall be sent out while we are still waiting for response to the first
command,
so there is a mutex mechanism in the DLL which prevents other threads
to execute commands through the DLL until the current function call has
completed.

- In my Application I have a couple of thread-driven timers which are
responsible
for generating periodic update commands to the slave unit. If I use
Synchronize()
on the timer event handler, the call is executed from the Main VCL thread
and as
a natural consequence the mutex mechanism in the DLL then doesn't work;
What DID baffle me was that apparently even though the Main Thread was
already
busy executing a DLL call of the SendCommandString type at the time when
the
thread timer kicked in, a second call would be allowed immediately when
Synchronize() was used (thus interferring with the ongoing Main Thread
call), so
our solution was to NOT use Synchronize(), which made the Mutex mechanism
in the DLL take effect.

The observation above indicates that Martin Larsson is right... and which
is why
I have become puzzled about the real workings of Synchronize().

So if Martin is right, and SendMessage immediately calls WndProc of the
Main window
(=Main VCL Thread, "most of the time", how is this defined?), it would seem
that Synchronize is indeed NOT a guarantee for thread-safe operation!

Kristofer Skaug
kristo...@skaug.demon.nl

David Rifkind <drifk...@acm.deleteme.org> wrote in article
<35e22780.29433...@netnews.worldnet.att.net>...

Quote
> On Mon, 24 Aug 1998 23:51:00 +0200, martin.lars...@delfidata.no.NOSPAM
> (Martin Larsson) wrote:
> >In article <903991260.29123.2.rover.c29fe...@news.demon.nl>, "Zweitze de
> >Vries" <zweitze.at.iname.com> ("Zweitze de Vries"

<zweitze.at.iname.com>)
Quote
> >says...
> >> The main thread will finish its current business first. The
synchronized
> >> function will be called when the main thread enters the message loop.
This
> >> is also the case when the main thread calls

Application.ProcessMessages.
Quote

> >Actually, no. At least not in Delphi 3. The TThread.Synchronize method
> >uses SendMessage. SendMessage immediately calls the WndProc of the given
> >window, and does not return until processing of the message is done.

> Only within the same thread.  When you send a message to another thread,
> it doesn't get delivered until the receiving thread retrieves messages.

> >The handler for CM_EXECPROC simply calls the desired function directly.

> >M.

> --
> Report all {*word*201} mail to your Potsmaster.

Re:Main Thread reaction to TThread.Synchronize()


On Tue, 25 Aug 1998 11:14:33 GMT, "Kristofer Skaug"

Quote
<kristo...@skaug.demon.nl> wrote:
>- I have a Delphi app which uses a C++ DLL which handles blocking TCP/IP
>sockets to communicate with an external slave unit. For example, when
>I use a DLL function call SendCommandString(pCommand,pResponse), the
>command contained in the PChar pCommand is sent out over the socket and
>the DLL holds out until an ASCII response string is received from the other
>side
>(with a certain timeout, of course). Now the intention is that no other
>commands
>shall be sent out while we are still waiting for response to the first
>command,
>so there is a mutex mechanism in the DLL which prevents other threads
>to execute commands through the DLL until the current function call has
>completed.

Blocking socket calls dispatch messages while they're blocking.  This
sounds nuts if you're thinking of UNIX system socket calls, but it's a
holdover from 16-bit Windows.

Quote
>- In my Application I have a couple of thread-driven timers which are
>responsible
>for generating periodic update commands to the slave unit. If I use
>Synchronize()
>on the timer event handler, the call is executed from the Main VCL thread
>and as
>a natural consequence the mutex mechanism in the DLL then doesn't work;
>What DID baffle me was that apparently even though the Main Thread was
>already
>busy executing a DLL call of the SendCommandString type at the time when
>the
>thread timer kicked in, a second call would be allowed immediately when
>Synchronize() was used (thus interferring with the ongoing Main Thread
>call), so
>our solution was to NOT use Synchronize(), which made the Mutex mechanism
>in the DLL take effect.

You might do better doing your blocking calls from somewhere other than
the main thread.  If a thread has no message queue, the blocking calls
won't dispatch any messages, and you'll have no reentrancy problems.

--
Report all {*word*201} mail to your Potsmaster.

Re:Main Thread reaction to TThread.Synchronize()


In article <35e22780.29433...@netnews.worldnet.att.net>, David Rifkind
(drifk...@acm.deleteme.org) says...

Quote
> Only within the same thread.  When you send a message to another thread,
> it doesn't get delivered until the receiving thread retrieves messages.

Ah. Ok. Sorry. Remembered too much of Win 3.x I guess.

Quote
> Report all {*word*201} mail to your Potsmaster.

What's a Potsmaster?

M.

--
Ettertraktet kaffe, er det ekstra god kaffe?
mailto:martin.lars...@delfidata.no.NOSPAM
http://www.delfidata.no/users/~martin

Re:Main Thread reaction to TThread.Synchronize()


Quote

> What DID baffle me was that apparently even though the Main Thread was
> already busy executing a DLL call of the SendCommandString type at the
> time when the thread timer kicked in, a second call would be allowed
> immediately when Synchronize() was used (thus interferring with the
> ongoing Main Thread call), so our solution was to NOT use Synchronize(),
> which made the Mutex mechanism in the DLL take effect.

There has to be some confusion here. The Main thread cannot both blocked
and able to execute a function via Synchronize. Was the main thread in the
DLL somehow processing messages? If it was then it is not really blocked
you are just busy waiting. In that case it would act just as you describe.

In general you shouldn't mix using Synchronize and Mutexes to protect a
common resource. You have to use one or the other. If you really have to do it
then you have to check if the mutex is owned by the current thread to avoid
grabing it again.

Other Threads