Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从线程调用ActiveX DLL_C#_Python_Multithreading_Dll_Activex - Fatal编程技术网

C# 从线程调用ActiveX 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

我有一个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实例可以建立连接。

我没有使用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按预期运行?