当你制作一个 ActiveX/COM 组件时,你可以为你的组件指定线程模型,它可以是例如“compartmentalized”。根据您的选择,ActiveX/COM 负责序列化请求。
如果您多次“打开”和 ActiveX/COM 组件(取决于线程模型?)实际上只会创建一个实例。
我假设您使用 win32com.client.Dispatch(".") 来“打开”您的 ActiveX/COM 组件。
另外,不要忘记 pythoncom.CoInitialize() 和 CoUninitialize() 对调用。
谷歌上那些实际做了什么。
如果您无法更改给定的 ActiveX/COM 组件并且其线程模型不可接受,则可以将所有“出站”调用包装在一个具有监视器“接口”的专用 Python 线程中。
这是我曾经遇到类似情况时编写的代码的大纲:
class Driver(threading.Thread):
quit = False # graceful exit
con = None
request = None
response = None
def __init__(self, **kw):
super(Driver, self).__init__(**kw)
self.setDaemon(True) # optional, helps termination
self.con = threading.Condition()
self.request = None
self.response = None
def run(self):
pythoncom.CoInitialize()
handle = win32com.client.Dispatch("SomeActiveX.SomeInterface")
try:
with self.con:
while not self.quit:
while not self.request: self.con.wait() # wait for work
method, args = self.request
try: self.response = getattr(handle, method)(*args), None # buffer result
except Exception, e: self.response = None, e # buffer exception
self.con.notifyAll() # result ready
finally:
pythoncom.CoUninitialize()
def call(method, *args):
with self.con:
while self.request: self.con.wait() # driver is busy
self.request = method, args
self.con.notifyAll() # driver can start
while not self.response: self.con.wait() # wait for driver
rv, ex = self.response
self.request = self.response = None # free driver
self.con.notifyAll() # other clients can continue
if ex: raise ex
else: return rv