[Twisted-Python] Creating a COM object in a thread

Hugh Emberson hugh.emberson at gmail.com
Wed Jun 30 20:02:22 MDT 2010


The way I do this is I isolate all the COM stuff in a separate thread
from thread that runs my reactor.

This thread starts by calling:

    pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED)

it then creates the COM object and runs an event loop something like this:

    while keepRunning:
        n = MsgWaitForMultipleObjects(handles, False, timeout, QS_ALLINPUT)
        if n == WAIT_OBJECT_0 + nHandles:
            # There is a win32 message waiting.
            if pythoncom.PumpWaitingMessages():
                keepRunning = False

I send messages to the thread by putting them in a queue and setting
an event.  The messages cause methods to be called on the COM object.
I send the results of the COM methods back to the reactor thread using
reactor.callFromThread().

It's a bit of effort to do this, but it works really well.  It's been
in production for several years and I've never had a problem with it.

Hope this helps,
Hugh

On Tue, Jun 29, 2010 at 10:43 AM, Don Dwiggins <ddwiggins at advpubtech.com> wrote:
>
> I need to create a COM object in a Windows application, and call it.
> Since the call will take some time to execute, I wrap it in a deferToThread.
>
> I've found that, when I create the object inline, it works.  However,
> when I defer it, it hangs up in the win32com.client.Dispatch call.  I've
> tried several things, including digging into the guts of Dispatch -- the
> hangup occurs during the creation of the object.
>
> I've discussed this with Mark Hammond, who suggests one lead:
>
> "The Windows message loop is used by the COM marshalling process.  IIRC,
> the first thread to initialize COM in a process is the thread in which
> single-threaded objects will always end up being called in.  If a
> different thread creates the object, COM uses Windows messages to
> marshall all calls back to that main thread.  IOW, your second thread
> makes a call - even to create the object - which results in that thread
> sending a windows message to the main thread to act on the request.
>
> What this probably means in practice is that twisted needs to use a
> reactor which calls MsgWaitForMultipleObjects() and runs a message loop
> when the function detects a new message is in the queue.  I'm not sure
> if there is an existing reactor which does this."
>
> I'm posting this on the off chance that someone else has wandered into
> this corner of Windows arcana, and has come up with something useful.
>
> I'm about to give up on doing this "inside" the twisted app, and running
> it in a separate app that I'll call from the thread.
>
> TIA,
> --
> Don Dwiggins
> Advanced Publishing Technology
>
>
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python




More information about the Twisted-Python mailing list