PyXR

c:\python24\lib\site-packages\win32 \ com \ test \ testMarshal.py



0001 """Testing pasing object between multiple COM threads
0002 
0003 Uses standard COM marshalling to pass objects between threads.  Even
0004 though Python generally seems to work when you just pass COM objects
0005 between threads, it shouldnt.
0006 
0007 This shows the "correct" way to do it.
0008 
0009 It shows that although we create new threads to use the Python.Interpreter,
0010 COM marshalls back all calls to that object to the main Python thread,
0011 which must be running a message loop (as this sample does).
0012 
0013 When this test is run in "free threaded" mode (at this stage, you must
0014 manually mark the COM objects as "ThreadingModel=Free", or run from a
0015 service which has marked itself as free-threaded), then no marshalling
0016 is done, and the Python.Interpreter object start doing the "expected" thing
0017 - ie, it reports being on the same thread as its caller!
0018 
0019 Python.exe needs a good way to mark itself as FreeThreaded - at the moment
0020 this is a pain in the but!
0021 
0022 """
0023 
0024 import thread, traceback
0025 import win32com.client
0026 import win32event, win32api
0027 import pythoncom
0028 
0029 from testservers import TestInterp
0030 
0031 freeThreaded = 1
0032 
0033 def TestInterpInThread(stopEvent, interp):
0034     try:
0035         DoTestInterpInThread(interp)
0036     finally:
0037         win32event.SetEvent(stopEvent)
0038 
0039 def DoTestInterpInThread(interp):
0040     try:
0041         pythoncom.CoInitialize()
0042         myThread = win32api.GetCurrentThreadId()
0043 
0044         if freeThreaded:
0045             interp = pythoncom.CoGetInterfaceAndReleaseStream(interp, pythoncom.IID_IDispatch)
0046             interp = win32com.client.Dispatch(interp)
0047 
0048         TestInterp(interp)
0049         interp.Exec("import win32api")
0050         print "The test thread id is %d, Python.Interpreter's thread ID is %d" % (myThread, interp.Eval("win32api.GetCurrentThreadId()"))
0051         interp = None
0052         pythoncom.CoUninitialize()
0053     except:
0054         traceback.print_exc()
0055 
0056 def BeginThreadsSimpleMarshal(numThreads):
0057     """Creates multiple threads using simple (but slower) marshalling.
0058 
0059     Single interpreter object, but a new stream is created per thread.
0060 
0061     Returns the handles the threads will set when complete.
0062     """
0063     interp = win32com.client.Dispatch("Python.Interpreter")
0064     ret = []
0065     for i in range(numThreads):
0066         hEvent = win32event.CreateEvent(None, 0, 0, None)
0067         interpStream = pythoncom.CoMarshalInterThreadInterfaceInStream(pythoncom.IID_IDispatch, interp._oleobj_)
0068         thread.start_new(TestInterpInThread, (hEvent, interpStream))
0069         ret.append(hEvent)
0070     return ret
0071 
0072 #
0073 # NOTE - this doesnt quite work - Im not even sure it should, but Greg reckons
0074 # you should be able to avoid the marshal per thread!
0075 def BeginThreadsFastMarshal(numThreads):
0076     """Creates multiple threads using fast (but complex) marshalling.
0077 
0078     The marshal stream is created once, and each thread uses the same stream
0079 
0080     Returns the handles the threads will set when complete.
0081     """
0082     interp = win32com.client.Dispatch("Python.Interpreter")
0083     if freeThreaded:
0084         interp = pythoncom.CoMarshalInterThreadInterfaceInStream(pythoncom.IID_IDispatch, interp._oleobj_)
0085     ret = []
0086 
0087     for i in range(numThreads):
0088         hEvent = win32event.CreateEvent(None, 0, 0, None)
0089         thread.start_new(TestInterpInThread, (hEvent, interp))
0090         ret.append(hEvent)
0091     return ret
0092 
0093 def test(fn):
0094     print "The main thread is %d" % (win32api.GetCurrentThreadId())
0095     events = fn(2)
0096     numFinished = 0
0097     while 1:
0098         try:
0099         # Specifying "bWaitAll" here seems to prevent messages???
0100             rc = win32event.MsgWaitForMultipleObjects(events, 0, 2000, win32event.QS_ALLINPUT)
0101             if rc >= win32event.WAIT_OBJECT_0 and rc < win32event.WAIT_OBJECT_0+len(events):
0102                 numFinished = numFinished + 1
0103                 if numFinished >= len(events):
0104                     break
0105             elif rc==win32event.WAIT_OBJECT_0 + len(events): # a message
0106                 # This is critical - whole apartment model demo will hang.
0107                 pythoncom.PumpWaitingMessages()
0108             else: # Timeout
0109                 print "Waiting for thread to stop with interfaces=%d, gateways=%d" % (pythoncom._GetInterfaceCount(), pythoncom._GetGatewayCount())
0110         except KeyboardInterrupt:
0111             break
0112 
0113 if __name__=='__main__':
0114     test(BeginThreadsSimpleMarshal)
0115 #       test(BeginThreadsFastMarshal)
0116     win32api.Sleep(500)
0117     # Doing CoUninit here stop Pythoncom.dll hanging when DLLMain shuts-down the process
0118     pythoncom.CoUninitialize()
0119     if pythoncom._GetInterfaceCount()!=0 or pythoncom._GetGatewayCount()!=0:
0120         print "Done with interfaces=%d, gateways=%d" % (pythoncom._GetInterfaceCount(), pythoncom._GetGatewayCount())
0121     else:
0122         print "Done."
0123 

Generated by PyXR 0.9.4
SourceForge.net Logo