2012-06-07 2 views
1

Windows 시스템 호출 (예 : ReadFile() 및 WriteFile())을 만드는 ActiveX (COM) DLL이 있습니다. 내 GUI (Python 또는 C#)는 기본 GUI 스레드에서 DLL의 인스턴스를 만듭니다. 그러나 스레드에서 스레드를 호출하려면 C# 또는 Python을 사용하지 않아도 각 스레드에 DLL의 새 인스턴스를 만들어야합니다. (참고로, 원래 인스턴스는 C#의 스레드에서 호출 할 수 있지만이 스레드는 주 스레드를 차단하므로 Python에서이 작업을 수행하면 GUI가 충돌합니다.) 스레드에 DLL의 새 인스턴스를 만드는 것을 피할 수있는 방법이 있습니까?스레드에서 호출 된 ActiveX DLL

원본 DLL 인스턴스를 사용하는 이유 : DLL에서 HID 마이크로 컨트롤러에 연결할 수 있습니다. DLL은 마이크로 컨트롤러에 하나의 전용 핸들을 허용하는 옵션을 제공합니다. GUI 디자이너가이 옵션 (특정 상황에서 필요함)을 선택하면 두 번째 DLL 인스턴스가 원하는대로 작동하지 않습니다. 단 하나의 DLL 인스턴스 만 연결을 만들 수 있기 때문입니다.

+0

스레드에서 새로운 인스턴스를 만드는 문제가 무엇 :

여기에 한번 비슷한 상황에 직면 쓴 코드에 대한 개요입니까? 그냥 그것을 피하기 위해? – Quintium

+0

좋은 질문입니다. 나는 원래의 질문을 중요한 세부 사항으로 업데이트했다. – tosa

+0

ActiveX는 GUI 스레드와 STA가 호출 할 수 있습니다. [이 게시물을 참조하십시오] (http://stackoverflow.com/questions/5497796/background-worker-issue). ActiveX 스레드를 사용하려면 백그라운드 스레드에서 GUI 스레드로 호출을 마샬링해야합니다. –

답변

1

필자는 Phyton을 사용하지 않았지만 C#에서는 정적 공용 속성으로 ActiveX가 포함 된 도우미 클래스를 만드는 것이 좋습니다. 기본 스레드가 ActiveX를 생성 한 다음 모든 스레드가 필요에 따라 액세스합니다.

+0

DLL 인스턴스가 여전히 주 스레드에 있으므로 도움이되지 않습니다. – tosa

1

ActiveX/COM 구성 요소를 만들 때 구성 요소에 대한 스레딩 모델을 지정할 수 있습니다. 예를 들어. "compartmentalized". 어떤 것을 선택 하느냐에 따라 ActiveX/COM이 직렬화 요청을 처리합니다.

"열기"및 ActiveX/COM 구성 요소를 여러 번 (스레딩 모델에 따라 다름) 하나의 인스턴스 만 실제로 생성됩니다.

ActiveX/COM 구성 요소를 "열기"위해 win32com.client.Dispatch (".")를 사용한다고 가정합니다.

또한 pythoncom.CoInitialize()와 CoUninitialize() 호출 쌍을 잊지 마십시오.

구글이 실제로하는 일에 관한 것.

해당 ActiveX/COM 구성 요소를 변경할 수없고 해당 스레딩 모델을 사용할 수없는 경우 모니터 "인터페이스"가있는 전용 파이썬 스레드에서 모든 "아웃 바운드"호출을 래핑 할 수 있습니다.

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 
+0

이것은 좋은 생각이며 테스트 중입니다. 그러나 DLL의 한 함수에서 RegisterDeviceNotification()이 호출되며 호출 될 때 내 GUI가 중단됩니다. GUI 스레드에서 호출 된 경우 제대로 작동합니다. 다른 스레드에서 호출 할 때 GUI 스레드에서 직접 호출 할 때와 같이 양식의 핸들을 수신하고 있기 때문에 어떤 문제가 발생하는지 확신 할 수 없습니다.
또한 DLL을 수정할 수있는 권한이 있습니다. 그것은 STA로 만들어졌습니다. MTA에 대한 옵션이 없습니다. DLL을 원하는대로 동작하게하려면 어떻게해야할까요? – tosa