Multithreaded COM server problem...
jl at windsmith.net
Wed Jan 21 15:10:12 CET 2004
Mark Hammond <mhammond at skippinet.com.au> wrote (with possible
> Is there any way you can do it asynchronously? The main thread spawns a
> second thread to do the work. The main thread then spins around a
> MsgWaitForMultipleObjects, with an object set by the second thread. The
> main thread will then be able to run a message pump, but also detect
> when the second thread is done.
Yes, except there doesn't seem to be any way to return a value from
the first call until after the second call completes.
> Apart from that, I am afraid I am out of ideas. I believe however that
> you are hitting pure COM issues, and nothing related to Python. Looking
> for the answer beyond the Python world may be fruitful.
The three reasonable possibilities I see at the moment are:
1. Dig into exactly how apartment-threaded servers are supposed to be
written in C or C++ & see how much of that is transferrable to Python.
I'm not confident this would give me a solution, though.
2. Activate the server in 2 steps -- have the main thread create (on
client request) "interlock" object that, when created, fires up a new
thread for the client who created it. The new thread then calls
factory.RegisterClassFactories() for the real worker object, then
starts a message pump. The client then requests COM to create the
worker object. The worker object creation method then calls
factory.RevokeClassFactories() to revoke that thread's registration.
The interlock and worker classes have to coordinate so that only one
worker thread is registered as class factory at any time, and only one
client is able to create the worker object at any time. The main
thread also has to register as class factory only for the interlock
object, not for the worker object. This requires changes to one py2exe
module and to all applications that use my server, and will complicate
shutdown, since I have to shut down the new thread only when all
object's it's pumping messages for are gone. There's also the
substantial possibility that the same bug I ran into when setting
sys.coinit_flags=0 in localserver.py will rear its head here.
3. Dig into why setting sys.coinit_flags=0 in localserver.py doesn't
work. This is probably the right thing to do, both because I know it
will yield a solution, and because it would solve the same issue for
anyone else with similar needs. Unfortunately it means I have to dig
into Python threading internals, pythoncom internals, and the whole
COM mechanism rather more heavily than I'd hoped to.
More information about the Python-list