Tim Roberts wrote |These are synchronous events. That is, these events are generated |directly by the requests you made. I believe you will find that the |"OnVisible" callback occurs before "ie.Visible = 1" returns. It's being |handled by that same thread, which is suspended waiting for IE to |finish. A message pump is only required for events that arrive |asynchronously. It's still single threaded. | |If you're familiar with the Windows GUI, this is similar to the |difference between PostMessage and SendMessage (ignoring interprocess |calls for now). SendMessage calls directly into the window procedure of |the target window without going through the message queue; when it |returns, the message is handled. PostMessage is fire-and-forget; it |will be processed later, when the message loop gets around to pulling |the message.
That clears up a lot. Thanks. I rewrote the test, see below. When run it behaves as you suggest (see the test output below). In particular the OnVisible event occurs synchronously before return from 'ie.Visible = 1' as you suggested. I checked StatusBar and it appears to be synchronous as well. I assume then that any events associated with setting IE's properties would also be synchronous, wouldn't they? But note that when I set StatusBar false the OnStatusBar event occurs. Then when I set StatusBar true both OnCommandStateChange and OnStatusBar events occur. I expected the OnStatusBar event but NOT the OnCommandStateChange event as later in the test (after 21.407) OnCommandStateChange behaves asynchronously. Is there some bit of behavior such that when a synchronous event occurs other queued events are also processed? About a year ago, Mark Hammond helped me in this area and memory serves that when any events are processed they are all processed. Is this true? Is this behavior a function of COM or of the Python COM interface? More generally, how do I know what COM interactions will generate synchronous events and which will cause asynchronous events? Interestingly if I comment out the code starting at line 47 (the trailing PUMP for the first navigation) I get a pythoncom error and trace like this: --- begin output --- Spin for 20 seconds pythoncom error: Python error invoking COM method. Traceback (most recent call last): File "C:\Python25\Lib\site-packages\win32com\server\policy.py", line 285, in _Invoke_ return self._invoke_(dispid, lcid, wFlags, args) File "C:\Python25\Lib\site-packages\win32com\server\policy.py", line 290, in _invoke_ return S_OK, -1, self._invokeex_(dispid, lcid, wFlags, args, None, None) File "C:\Python25\Lib\site-packages\win32com\server\policy.py", line 588, in _invokeex_ return func(*args) File "C:\rbell\Bell Curve Group\IE Testing\test070607a.py", line 17, in OnCommandStateChange print 'At %6.3f OnCommandStateChange: %s %s'%(time.clock(),Command,Enable) <type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'clock' --- end output --- At that point IE is still running and as the test is coming down there appears to be a window where events start flowing into the event routines but there is not enough of the Python/test application still available to handle them. I'm not sure that this is a bug or just an unfortunate boundary condition. Based on what I think I understand about COM automation I'm inclined to think that this condition can occur on any COM interface with event support. At any event thanks again for your input. It was very helpful. FWIW, anyone looking at this code should know that it is NOT best/good/OK practice. It's just something I hacked together to explore this issue and should NOT be used as a base for anything but experimentation. --- begin code --- # test events WITHOUT a message pump import win32com.client import pythoncom import time class events(): def OnVisible(self, vis): print 'At %6.3f OnVisible is %s'%(time.clock(),vis) def OnBeforeNavigate2(self,pDisp,url,flags, targetFrameName,postData, headers,cancel): print "At %6.3f OnBeforeNavigate2 on url [%s] on frame [%s]"% \ (time.clock(), url, targetFrameName) def OnCommandStateChange(self, Command, Enable): print 'At %6.3f OnCommandStateChange: %s %s'% \ (time.clock(),Command,Enable) def OnProgressChange(self, nProgress, nProgressMax): msg = 'At %6.3f OnProgressChange progress %d max %d' % ( time.clock(),nProgress, nProgressMax) print msg def OnStatusBar(self, status): msg = 'At %6.3f OnStatusBar %s'%(time.clock(),status) print msg time.clock() # just get clock running print 'At %6.3f win32com.client.DispatchWithEvents'%time.clock() ie = win32com.client.DispatchWithEvents( 'InternetExplorer.Application', events) # NO PUMP MESSAGE print 'At %6.3f set ie.Visible'%time.clock() ie.Visible = 1 print 'At %6.3f set ie.StatusBar false'%time.clock() ie.StatusBar = 0 print 'At %6.3f set ie.StatusBar true'%time.clock() ie.StatusBar = 1 print 'At %6.3f Navigate to http://msdn2.microsoft.com/en-us/library/aa752574.aspx'%time.clock() url = 'http://msdn2.microsoft.com/en-us/library/aa752574.aspx' ie.Navigate(url) print 'At %6.3f back from Navigate'%time.clock() print 'The page should NOT be displayed' print 'Spin for 20 seconds' t0 = time.clock() while time.clock()-t0 < 20: pass print 'At %6.3f pump any trailing messages'%time.clock() print 'The page should NOW display' t0 = time.clock() while time.clock()-t0 < 20: pythoncom.PumpWaitingMessages() # PUMP MESSAGES print '*'*50 print 'At %6.3f Navigate WITH PUMP to http://msdn2.microsoft.com/en-us/library/aa752514.aspx'%time.clock() url = 'http://msdn2.microsoft.com/en-us/library/aa752514.aspx' ie.Navigate(url) print 'At %6.3f back from Navigate and PUMPING'%time.clock() t0 = time.clock() while time.clock()-t0 < 20: pythoncom.PumpWaitingMessages() print 'At %6.3f terminate'%time.clock() --- end code --- --- begin complete test output --- At 0.000 win32com.client.DispatchWithEvents At 1.250 set ie.Visible At 1.299 OnVisible is True At 1.305 set ie.StatusBar false At 1.324 OnStatusBar False At 1.329 set ie.StatusBar true At 1.343 OnCommandStateChange: 2 False At 1.355 OnStatusBar True At 1.356 Navigate to http://msdn2.microsoft.com/en-us/library/aa752574.aspx At 1.358 OnCommandStateChange: 1 False At 1.374 OnBeforeNavigate2 on url [http://msdn2.microsoft.com/en-us/library/aa752574.aspx] on frame [] At 1.407 back from Navigate The page should NOT be displayed Spin for 20 seconds At 21.408 pump any trailing messages The page should NOW display At 21.408 OnCommandStateChange: 2 False At 21.409 OnCommandStateChange: 1 False At 21.444 OnProgressChange progress 0 max 10000 At 21.715 OnCommandStateChange: -1 False At 21.791 OnCommandStateChange: 2 False At 21.798 OnCommandStateChange: 1 False At 21.849 OnCommandStateChange: -1 False At 21.942 OnProgressChange progress 50 max 10000 At 22.441 OnProgressChange progress 100 max 10000 At 22.471 OnProgressChange progress 258300 max 1000000 At 22.472 OnProgressChange progress 272200 max 1000000 At 22.486 OnProgressChange progress 339200 max 1000000 At 22.494 OnProgressChange progress 422900 max 1000000 At 22.557 OnProgressChange progress 1006800 max 1000000 At 27.806 OnProgressChange progress 1000000 max 1000000 At 27.807 OnProgressChange progress -1 max 1000000 At 27.824 OnProgressChange progress 1000000 max 1000000 At 28.115 OnBeforeNavigate2 on url [http://msdn2.microsoft.com/en-us/library/aa752574(d=toc).aspx] on frame [] At 28.138 OnProgressChange progress 1000000 max 10000 At 28.167 OnCommandStateChange: -1 False At 28.306 OnProgressChange progress 0 max 0 At 29.552 OnProgressChange progress 54300 max 1000000 At 29.555 OnProgressChange progress 129300 max 1000000 At 29.557 OnProgressChange progress 214900 max 1000000 At 29.560 OnProgressChange progress 338300 max 1000000 At 29.584 OnProgressChange progress 449600 max 1000000 At 29.587 OnProgressChange progress 476400 max 1000000 At 29.594 OnProgressChange progress 554300 max 1000000 At 29.820 OnCommandStateChange: 2 False At 29.820 OnCommandStateChange: 1 False At 37.530 OnProgressChange progress 1000000 max 1000000 At 37.531 OnProgressChange progress -1 max 1000000 At 37.672 OnCommandStateChange: -1 False At 38.053 OnProgressChange progress 0 max 0 ************************************************** At 41.408 Navigate WITH PUMP to http://msdn2.microsoft.com/en-us/library/aa752514.aspx At 41.414 back from Navigate and PUMPING At 41.430 OnBeforeNavigate2 on url [http://msdn2.microsoft.com/en-us/library/aa752514.aspx] on frame [] At 41.600 OnProgressChange progress 0 max 10000 At 41.607 OnCommandStateChange: -1 False At 42.097 OnProgressChange progress 50 max 10000 At 42.212 OnProgressChange progress 11000 max 1000000 At 42.335 OnCommandStateChange: -1 False At 42.479 OnCommandStateChange: 2 True At 42.480 OnCommandStateChange: 1 False At 42.485 OnCommandStateChange: -1 False At 42.791 OnProgressChange progress 287700 max 1000000 At 42.803 OnProgressChange progress 465400 max 1000000 At 42.806 OnProgressChange progress 995300 max 1000000 At 46.091 OnProgressChange progress 1000000 max 1000000 At 46.092 OnProgressChange progress -1 max 1000000 At 46.102 OnProgressChange progress 1000000 max 1000000 At 46.400 OnBeforeNavigate2 on url [http://msdn2.microsoft.com/en-us/library/aa752514(d=toc).aspx] on frame [] At 46.425 OnProgressChange progress 1000000 max 10000 At 46.431 OnCommandStateChange: -1 False At 46.590 OnProgressChange progress 0 max 0 At 47.680 OnProgressChange progress 96400 max 1000000 At 47.684 OnProgressChange progress 171000 max 1000000 At 47.686 OnProgressChange progress 249300 max 1000000 At 47.700 OnProgressChange progress 424700 max 1000000 At 47.886 OnCommandStateChange: 2 True At 47.887 OnCommandStateChange: 1 False At 54.426 OnProgressChange progress 1000000 max 1000000 At 54.434 OnProgressChange progress -1 max 1000000 At 54.611 OnCommandStateChange: -1 False At 54.955 OnProgressChange progress 0 max 0 At 61.423 terminate --- end complete test output --- _______________________________________________ Python-win32 mailing list Python-win32@python.org http://mail.python.org/mailman/listinfo/python-win32