[python-win32] MsgWaitForMultipleObjects timeout

Michael Robin me@mikerobin.com
Wed, 20 Feb 2002 10:24:36 -0800


I originally got my code from timer_demo.py included in ..\win32com\test.
It looks like the argument order does not match TestMarshal.py (same place)
and SingleThreadedApartment, below.

# Timer_demo.py:
# This module, and the timer.pyd core timer support, were written by
# Sam Rushing (rushing@nightmare.com)
		rc = win32event.MsgWaitForMultipleObjects(
			(g.event,), # list of objects
			0, # wait all
			win32event.QS_ALLEVENTS, # type of input
			500) # timeout

# TestMarshal.py
		rc = win32event.MsgWaitForMultipleObjects(events, 0, 2000,
win32event.QS_ALLINPUT)

The correct (win32) order agrees with the latter. (I should have realized
this
as I've used the call from C in the past.)
Given that win32event.QS_ALLEVENTS == 191, the behavior I observed
makes sense.

It looks like timer_demo.py needs to be fixed.

This looks like one of those cases that pychecker (or even C) wouldn't
be able to see and that is hard to see in testing as well.
(In this case, the difference between 500 and 191ms timeout,
and the fact the ersatz message mask happened to work out.)

mike



-----Original Message-----
From: Jim Vickroy [mailto:Jim.Vickroy@noaa.gov]
Sent: Tuesday, February 19, 2002 9:47 AM
To: Michael Robin
Subject: Re: [python-win32] MsgWaitForMultipleObjects timeout


You are welcome.

I've done a brief search, and here is sample code from "Python Programming
on
Win32" by Hammond and Robinson.

Note, the comment:
        # A quirk in MsgWaitForMultipleObjects means we must wait
        # for each event one at at time

Let me know if this helps.


# begin
script ---------------------------------------------------------------
# SingleThreadedApartment.py
# Demonstrate the use of multiple threads, each in their own
# single-threaded apartment.

# As we do not set sys.coinit_flags=0
# before the Pythoncom import, Python
# initializes the main thread for single threading.
from pythoncom import \
     CoInitialize, CoUninitialize, IID_IDispatch,\
     CoMarshalInterThreadInterfaceInStream, \
     CoGetInterfaceAndReleaseStream, \
     PumpWaitingMessages

from win32event import \
     MsgWaitForMultipleObjects, \
     QS_ALLINPUT, WAIT_TIMEOUT, WAIT_OBJECT_0

from win32com.client import Dispatch
from win32process import beginthreadex
from win32api import GetCurrentThreadId

def Demo( prog_id ):
    # First create the object
    object = Dispatch(prog_id)
    print "Thread", GetCurrentThreadId(), "creating object"
    created_id = object.GetCreatedThreadId()
    print "Object reports it was created on thread", created_id
    # Now create the threads, remembering the handles.
    handles = []
    for i in range(3):
        # As we are not allowed to pass the object directly between
        # apartments, we need to marshal it.
        object_stream = CoMarshalInterThreadInterfaceInStream(
                          IID_IDispatch, object )
        # Build an argument tuple for the thread.
        args = (object_stream,)
        handle, id = beginthreadex(None, 0, WorkerThread, args, 0)
        handles.append(handle)
    # Now we have all the threads running, wait for them to terminate.
    # also remember how many times we are asked to pump messages.
    num_pumps = 0
    while handles:
        # A quirk in MsgWaitForMultipleObjects means we must wait
        # for each event one at at time
        rc = MsgWaitForMultipleObjects(handles, 0, 5000, QS_ALLINPUT)
        if rc >= WAIT_OBJECT_0 and rc < WAIT_OBJECT_0+len(handles):
            # A thread finished - remove its handle.
            del handles[rc-WAIT_OBJECT_0]
        elif rc==WAIT_OBJECT_0 + len(handles):
            # Waiting message
            num_pumps = num_pumps + 1
            PumpWaitingMessages()
        else:
            print "Nothing seems to be happening",
            print "but I will keep waiting anyway..."
    print "Pumped messages", num_pumps, "times"
    print "Demo of", prog_id, "finished."

def WorkerThread(object_stream):
    # First step - initialize COM
    CoInitialize() # Single-threaded.
    # Unmarshal the IDispatch object.
    object = CoGetInterfaceAndReleaseStream(
        object_stream, IID_IDispatch)
    # The object we get back is a PyIDispatch, rather
    # than a friendly Dispatch instance, so we convert
    # to a usable object.
    object = Dispatch(object)
    this_id = GetCurrentThreadId()
    that_id = object.GetCurrentThreadId()
    message = "Thread is %d, and object is on thread %d" % \
                                     (this_id, that_id)
    print message
    # Be a good citizen and finalize COM, but
    # first remove our object references.
    object = None
    CoUninitialize()

if __name__=='__main__':
    print "Running with Apartment Threaded object"
    Demo("PythonThreadDemo.Apartment")
    print
    print "Running with Free Threaded object"
    Demo("PythonThreadDemo.Free")
# end script ---------------------------------------------------------------



Michael Robin wrote:

> Thanks for trying - i'll
> send out any solutions I find...
>
> m
>
> -----Original Message-----
> From: Jim Vickroy [mailto:Jim.Vickroy@noaa.gov]
> Sent: Tuesday, February 19, 2002 8:40 AM
> To: Michael Robin
> Subject: Re: [python-win32] MsgWaitForMultipleObjects timeout
>
> Hello Mike,
>
> I have just run your script with Python 2.2 on a Win 2k machine with the
> same
> result you reported.  Setting timeout=5000 seemed to have no effect
either.
> I
> have never used this type of code so I do not understand the behavior
> either.
>
> Michael Robin wrote:
>
> > I'm having the problem of getting a timeout every
> > 200 ms or so, no matter what I use as the timeout
> > argument for MsgWaitForMultipleObjects. Anyone see
> > a problem here? Can someone
> > else run this and see if they get the same results?
> >
> > thanks,
> > mike
> >
> > ---------------------------------
> >
> > import win32event
> > import pythoncom
> > import time
> >
> > def messagePump():
> >         timeout = win32event.INFINITE
> >         event = win32event.CreateEvent(None, 0, 0, None)
> >
> >         while 1:
> >                 start = time.time()
> >
> >                 rc = win32event.MsgWaitForMultipleObjects(
> >                         (event,),
> >                         0, # wait all
> >                         win32event.QS_ALLEVENTS,
> >                         timeout)
> >
> >                 if rc == win32event.WAIT_TIMEOUT:
> >                         print "messageloop: Timeout %d" % int(1000 *
> > (time.time() - start))
> >
> > if __name__ == '__main__':
> >         messagePump()
> >
>
  ------------------------------------------------------------------------
> >                   Name: winmail.dat
> >    winmail.dat    Type: application/ms-tnef
> >               Encoding: base64