ActiveX / COMコンポーネントを作成する場合、コンポーネントのスレッドモデルを指定できます。たとえば、「コンパートメント化」することができます。どちらを選択するかに応じて、ActiveX/COMがリクエストのシリアル化を処理します。
ActiveX / COMコンポーネントを複数回「開く」場合(スレッドモデルによって異なりますか?)、実際には1つのインスタンスのみが作成されます。
Win32com.client.Dispatch( "。")を使用してActiveX/COMコンポーネントを「開く」ことを前提としています。
また、pythoncom.CoInitialize()とCoUninitialize()の呼び出しのペアを忘れないでください。
それらが実際に何をするかについてのグーグル。
特定のActiveX/COMコンポーネントを変更できず、そのスレッドモデルが受け入れられない場合は、すべての「アウトバウンド」呼び出しを、モニター「インターフェイス」を備えた1つの専用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