John Lull
I'm writing a multithreaded COM server to manage a pool of hardware resources. All objects are designed to be thread-safe, and I've set sys.coinit_flags to COINIT_MULTITHREADED before importing pythoncom.
The problem is that all requests to the server seem to be serialized by COM. To demonstrate the problem, I'm including a simple test server that exposes one interface object, PyComThreads.Application, with a single method sleep(delay). I'm also including 2 test programs -- test20.py uses the server to delay 20 seconds, and test1.py delays only one second. The server prints status messages to the trace collector debugging tool when creating the Application object, and at the beginning and end of the specified delay.
When I run the 20-second test program, then a couple seconds later run the 1-second test program, I had expected to see something like this:
Object 8087872 in thread 8160416 created Object 8087872 in thread 8160416 delays 20 seconds Object 8086008 in thread 8156272 created Object 8086008 in thread 8156272 delays 1 seconds Object 8086008 delay ends Object 8087872 delay ends
Instead, I see:
Object 8087872 in thread 8160416 created Object 8087872 in thread 8160416 delays 20 seconds Object 8087872 delay ends Object 8086008 in thread 8160416 created Object 8086008 in thread 8160416 delays 1 seconds Object 8086008 delay ends
Apparently the requests from both client applications are being serialized by the COM interface.
I need each request (or at least each interface object) to run in its own thread, or in a pool of threads, and haven't been able to figure out how to accomplish this. Any suggestions would be appreciated.
Regards, John
---------- PyComThreads.py:
import sys import threading from time import sleep import win32traceutil
sys.coinit_flags = 0 # 0 == pythoncom.COINIT_MULTITHREADED # !!!!! import pythoncom
class Application: """ Test version of a Multi-threaded local server """
_reg_progid_ = 'PyComThreads.Application' _reg_verprogid_ = 'PyComThreads.Application.100' _reg_clsctx_ = pythoncom.CLSCTX_LOCAL_SERVER _reg_clsid_ = '{56BEC27D-EDC4-43A0-AEB7-77E4A1381C0F}'
_public_methods_ = ['sleep'] _public_attrs_ = [] _readonly_attrs_ = []
def __init__(self): print 'Object %s in thread %s created' % \ (id(self), id(threading.currentThread()))
def sleep(self, delay): print 'Object %s in thread %s delays %s seconds' % \ (id(self), id(threading.currentThread()), delay) sleep(delay) print 'Object %s delay ends' % id(self)
# COM server registration, etc. if __name__ == '__main__': if hasattr(sys, 'argv'): # If *no* command-line arguments, we were not invoked as a server. # Assume the user wants us to self-register. if len(sys.argv) == 1: sys.argv.append('--register')
import win32com.server.register win32com.server.register.UseCommandLine(Applicatio n, debug=0)
---------- test20.py:
from win32com.client import Dispatch app=Dispatch('PyComThreads.Application') app.sleep(20)
---------- test1.py:
from win32com.client import Dispatch app=Dispatch('PyComThreads.Application') app.sleep(1)
|