TThread Synchronize hangs

TThread Synchronize hangs

Post by bilb » Thu, 19 Jul 2007 07:32:45


BCB6 patched.

I have a COM server. That server contains a background thread. The
background thread calls Syncronize(someMethod); However - "someMethod"
never gets called. The client application is a GUI. It created the COM
object, invokes a function which in turns starts the background thread.
This all seems to work OK. I see the thread later wake up and call the
Synchronize(someMethod) - where it hangs.

I also note that the GUI is responsive (and so is processing messages).

I also note that at the moment the GUI is closed, "someMthod" is called.

Any ideas?
 
 
 

TThread Synchronize hangs

Post by Team » Thu, 19 Jul 2007 07:54:52


An in-proc server or an out-of-proc server?


Then your app's main thread is not pumping the message queue for new VCL
messages.


Is it written in BCB 6 as well?


That does not necessarily mean that the GUI thread is processing the
messages that Synchronize() needs.


Gambit

 
 
 

TThread Synchronize hangs

Post by bilb » Thu, 19 Jul 2007 10:53:18


"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM > wrote

In-Proc.



Hmmm - odd, I wonder why?



Yes it is.
 
 
 

TThread Synchronize hangs

Post by Team » Thu, 19 Jul 2007 12:15:18


Synchronize() puts the specified method pointer into a global list, notifies
the main thread that it needs to process the list, and then waits for the
method to finish its work. However, a DLL does not have access to the main
application's list, and vice versa. Your code doesn't work because the DLL
is maintaining its own local list that the main app can't execute. So the
thread's method is stored in the DLL's list, which the app never calls, and
the thread becomes deadlocked.

The only reason your code wakes up on shutdown is because TThread's
destructor is checking the DLL's list and executing any stored methods while
waiting for the thread to exit. The destructor waits until the thread's
method finally executes, then the thread sees the Terminated property has
been set so it exits, allowing the destructor to finish its cleanup.

As such, you can't use Synchronize() in a DLL at all, because there is no
way to make the list be processed correctly. You will have to re-think your
DLL's design to use a different kind of synchronization.


Gambit
 
 
 

TThread Synchronize hangs

Post by bilb » Thu, 19 Jul 2007 23:32:21

Thanks Remy,

"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM > wrote
[...]

Let me explain what I need to accomplish and maybe you can suggest a better
way to do it.

1) The in-proc COM server is distributed to arbitrary third party
developers - so it has to use all COM standards.

2) The server is called once (say Foo()) from inside these client
applications and Foo() must start up a background thread (say ThreadX)
inside the server to perform some regular monitoring. It does this moniting
using a waitable timer and WaitForSingleObject(). The monitoring in ThreadX
is done repeatedly until the app exits. Foo returns and the client continues
while ThreadX does its work.

3) When ThreadX's timer fires and it detects a certain condition, it must
fire an IDispatch event (say EventX) to the client app (who of course had
previously connected a sink), passing some parameters, informing the client
that this certain event has ocurred. The client can respond as they like and
the EventX eventually retuns to the COM server. When EventX returns,
ThreadX goes back into the wait.

The waiting logic and event logic all seems to be working fine. I would
simply throw away Synchronize() and fire the event back at the client, but
thats not right. When I try that, I get *BizzArE* results in the client app
which I believe to be because it is not Synchronize()d. An example of this
bizzarre behaviour is: in the event handler in the client I just do a
MessageDlg(), but some times the dialog is so large it fills the entire
screen, other times it contains no caption or text, other times the button
is entirely the wrong size, etc.

Ideas?
 
 
 

TThread Synchronize hangs

Post by Team » Fri, 20 Jul 2007 01:54:46


Then I suggest you make the COM object be free-threaded, and let it call the
sink directly without any synchronization performed by the thread. Have the
application be responsible for its own synchronization as needed. Don't do
it inside the DLL itself.

Using threads inside of a COM object, especially when a sink is involved, is
a very tricky and very delicate thing to implement properly in general,
regardless of whether you are using the VCL or not.


It can be, if implemented properly in the COM object's code, and documented
correctly so the users know that their callbacks need to be thread-safe.
I've made multi-threaded COM objects before, so I know this approach can
work in general, though I've always implemented them as out-of-proc servers
instead of in-proc servers. I never have need to use threads in an in-proc
server.


MessageDlg() displays a VCL TForm, so it is not thread-safe. Use the Win32
API MessageBox() function instead.


Gambit