C# 从线程调用ActiveX DLL
我有一个ActiveX(COM)DLL,可以进行windows系统调用(例如ReadFile()和WriteFile())。我的GUI(Python或C#)在主GUI线程中创建DLL的实例。但是,为了从线程调用它,必须在每个线程中创建一个新的DLL实例,而不管使用C#还是Python。(作为旁注,可以从C#中的线程调用原始实例,但这会阻塞主线程;在Python中这样做会使GUI崩溃。)有没有办法避免在线程中创建DLL的新实例C# 从线程调用ActiveX DLL,c#,python,multithreading,dll,activex,C#,Python,Multithreading,Dll,Activex,我有一个ActiveX(COM)DLL,可以进行windows系统调用(例如ReadFile()和WriteFile())。我的GUI(Python或C#)在主GUI线程中创建DLL的实例。但是,为了从线程调用它,必须在每个线程中创建一个新的DLL实例,而不管使用C#还是Python。(作为旁注,可以从C#中的线程调用原始实例,但这会阻塞主线程;在Python中这样做会使GUI崩溃。)有没有办法避免在线程中创建DLL的新实例 需要使用原始DLL实例的原因是:DLL允许连接到HID微控制器。DLL
需要使用原始DLL实例的原因是:DLL允许连接到HID微控制器。DLL提供了一个选项,只允许微控制器有一个独占句柄。如果GUI设计器选择此选项(在某些情况下是必需的),则第二个DLL实例将无法按预期工作,因为只有一个DLL实例可以建立连接。我没有使用Phyton,但对于C,我建议创建一个包含ActiveX作为静态公共属性的帮助器类。让主线程创建ActiveX,然后所有线程根据需要从那里访问它 制作ActiveX/COM组件时,可以为组件指定线程模型,例如“划分”。ActiveX/COM负责序列化请求,具体取决于您选择的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
在线程中创建新实例有什么问题?只是为了避免它?好问题;我更新了原来的问题,因为这是一个重要的细节。ActiveX只能由GUI线程调用,而且也是一个STA线程。为了使用ActiveX对象,您需要将后台线程的调用封送到GUI线程。我相信我可以并且事实上确实可以在主线程以外的线程中创建ActiveX对象:“然而,为了从线程调用它,必须在每个线程中创建一个新的DLL实例,而不管使用的是C#还是Python”。然而,我的目标是不这样做。您能解释一下“然而,为了从线程调用它,必须在每个线程中创建一个新的DLL实例”是什么意思吗“在更多细节中,包括为什么会出现这种情况?没有帮助,因为DLL实例仍在主线程中。这是一个好主意,我正在测试它。”。但是,在DLL中的一个函数中有一个对RegisterDeviceNotification()的调用,调用时会挂起我的GUI。如果从GUI线程调用,那么它可以正常工作。我不确定为什么从另一个线程调用它会导致任何问题,因为它正在接收表单的句柄,就像直接从GUI线程调用时一样
此外,我有权修改DLL。它是由STA制成的;MTA没有选项。您有什么建议使DLL按预期运行?