从线程调用的ActiveX DLL

时间:2012-06-07 21:47:46

标签: 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提供了一个选项,只允许微控制器的一个独占句柄。如果GUI设计者选择此选项(在某些情况下是必需的),则第二个DLL实例将无法按预期工作,因为只有一个DLL实例可以进行连接。

2 个答案:

答案 0 :(得分:1)

我没有和Phyton合作过,但对于C#,我建议创建一个包含ActiveX作为静态公共属性的帮助器类。让主线程创建ActiveX,然后从那里所有线程根据需要访问它。

答案 1 :(得分:1)

制作ActiveX / COM组件时,您可以为组件指定线程模型,例如,它可以是"间隔化&#34 ;.根据您的选择,ActiveX / COM负责序列化请求。

如果你打开"和ActiveX / COM组件多次(取决于线程模型?)实际上只创建了一个实例。

我假设您使用win32com.client.Dispatch("。")来打开"打开"你的ActiveX / COM组件。

另外,不要忘记pythoncom.CoInitialize()和CoUninitialize()调用。

谷歌实际上做了什么。

如果您无法更改给定的ActiveX / COM组件且其线程模型不可接受,则可以将所有" outbound"在一个专用的Python线程中调用monitor" interface。"

这里是我曾经遇到过类似情况的代码大纲:

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