2012-06-17 3 views
0

는 자이 썬에서은 EDT에 메소드를 제출하는 Pythonesque 방법이 있습니까? 파이썬 하나에서

def runTaskInNonEDT(): 
    pass 
tRunTask = threading.Thread(target = runTaskInNonEDT) 
tRunTask.start() 

을 수행하는 데 사용됩니다, 나는 동부 서머 타임에 방법을 제출하려는 경우 당신이 모든 부수적을 분명히

def makeRunnableClass(): 
    class RunnableClass(Runnable): 
    def run(rSelf): 
     pass 
    return RunnableClass 
SwingUtilities.invokeAndWait(makeRunnableClass()()) 

을 가야 찾을 매개 변수를 전달하는 것에 관한 질문 등 EDT에 메서드를 제출하는 더 순진한 방법이 있을지 궁금한가요?

감사 @lvc ... 예, 사실 나는 사실 관용구

def makeSthgClass(): 
    class SthgClass(): 
    pass 
    return SthgClass 

하나는 내가 네임 스페이스를 어지럽히고 중지 습관적으로 만 사용하는 것을 ... 수 원샷 서브 클래 싱 된 인스턴스의 클래스 이름을 사용합니다.

나는 사실 그래서 당신은

def doSthg(): 
    pass 
self.runToMessageTree(doSthg) 

을 갈 수있는 작업

def runToMessageTree(self, method, *args, **kvargs): 
    if SwingUtilities.isEventDispatchThread(): 
    method(*args, **kvargs) 
    else: 
    def makeRunnableClass(): 
     class RunnableClass(Runnable): 
     def run(self): 
      method(*args, **kvargs) 
     return RunnableClass 
    SwingUtilities.invokeAndWait(makeRunnableClass()()) 

을 밝게 sthg도 있고 ...하지만 그것에 대해 만족스럽게 파이썬 아무것도 없다.

이상 :

class EDTWorkerThread(WorkerThread): 
    def __init__(ewt_self, name): 
     super(EDTWorkerThread, ewt_self).__init__(name) 
     class EDTWorker(SwingWorker): 
     def doInBackground(self): 
      check_event_thread(False) 
      while True: 
      method_call_elements = ewt_self.input_queue.get() 
      if method_call_elements is None: # "poison pill" 
       break 
      self.super__publish([ method_call_elements ]) 
      ewt_self.input_queue.task_done() 
      return 
     def process(self, chunks): 
      check_event_thread(True) 
      for chunk in chunks: 
      assert type(chunk) is list 
      assert chunk # i.e. must have at least one element! 
      # check that first item is callable 
      assert hasattr(chunk[ 0 ], "__call__") 
      method_call_elements = chunk 
      method_args = method_call_elements[ 1 : ] 
      method_call_elements[ 0 ](*method_args) 
      ewt_self.input_queue.task_done() 
     ewt_self.swing_worker = EDTWorker() 
    def run(self): 
     self.swing_worker.execute() 

의 WorkerThread는 아주 간단한, 고전 파이썬 관용구이다

class WorkerThread(threading.Thread): 
    def __init__(self, *args, **kvargs): 
    threading.Thread.__init__(self, *args, **kvargs) 
    self.input_queue = Queue() 

    def send(self, item): 
    assert type(item) is list 
    assert item # i.e. must have at least one element! 
    # check that first item is callable 
    assert hasattr(item[ 0 ], "__call__") 
    self.input_queue.put(item) 

    def close(self): 
    self.input_queue.put(None) 
    self.input_queue.join() 

    def run(self): 
    while True: 
     method_call_elements = self.input_queue.get() 
     if method_call_elements is None: # "poison pill" 
     break 
     method_args = method_call_elements[ 1 : ] 
     method_call_elements[ 0 ](*method_args) 
     self.input_queue.task_done() 
    self.input_queue.task_done() 
    return 

그래서 당신이 선택 인수 다음 방법을 제출 ...이 방법은 다음되고 실행 끝 EDT에서는 문제의 args를 사용합니다. 실행 파일을 생성 할 필요가 없습니다 ...

물론 다른 가능성은 SwingWorker에서 하위 클래스로 만드는 것입니다 ... 그러면이 두 가지 문제가있는 "이중 대기열"배열 (예 : WorkerThread Queue 및 EDT 자체 공정())에 전달한다 ...하지만 당신은 doInBackground에서) (수면 (사용)하지 않고 우아 루프를 가져야 큐, ...

사람들의 견해

+0

는, 실제로 그 사람을 통지하지 않습니다 - 일반적인 관행을 업데이트하는 것입니다 당신이 그것을 업데이트했다는 것을 그들의 대답 (또는 그들이 코멘트 한 @ 사람의 코멘트)에 코멘트를 게시하십시오. – lvc

+0

... 그리고 그렇게 말하면서 나는 똑같은 일을했다. 내 업데이트 된 답변을 참조하십시오. 이것에 대해 – lvc

답변

1

주요 점에서 관심을 가질만한 깨닫기 위해서는 SwingUtilities.invokeAndWait이 Java가 일류 함수를 가지고 있지 않기 때문에 단일 메소드 인터페이스의 인스턴스를 기대합니다. 이 기능을 위해서는 더 많은 Pythonic 인터페이스가있는 SwingUtilities 이외의 것을 사용하지 않으면 해당 비트를 피할 수 없습니다.

마음이 특정 API를 사용하도록 설정되어있는 경우에도 래퍼 기능을 사용하지 않아도됩니다.그냥 수행

class RunnableClass(Runnable): 
    def run(self): 
     pass 

SwingUtilities.invokeAndWait(RunnableClass()) 

래퍼 기능을 사용하는 유일한 이유는 클로저를 사용 run에서 호출 할 수있는 기능을 통과 사용할 수있게하는 것입니다; 당신은 여전히 ​​RunnableClass.__init__으로 기능을 전달하고 저장하여이 작업을 수행 할 수 있습니다

class RunnableClass(Runnable): 
    def __init__(self, func): 
     self._func = func 

    def run(self): 
     self._func() 

참고 func는 첫 번째 매개 변수로 self을하지한다 - 인스턴스에 그것의 속성 때문에 오히려 클래스보다, 방법으로 취급되지 않습니다. 당신의 편집 당

-RunnableClass.__init__func를 전달하는 지점이 더 이상 원샷 서브 클래스를 할 필요가 없다는 것입니다 - 당신은 당신이 실행하는거야 모든 FUNC에 대한 Runnable 중 하나 개 서브 클래스를 필요로하지 않습니다, RunnableClass의 인스턴스가 하나뿐입니다. 클래스 그 자체 인은 파이썬 관용구에서 자바에 이르기까지 일반적인 어댑터이므로 동일한 작업을 수행하는 데 주변에 함수가 필요하지 않습니다.

이 당신의 runToMessageTree은 다음과 같이 할 수 있습니다 의미 : 당신이 그것에 @person 말하더라도, 당신의 질문을 수정

def runToMessageTree(self, method, *args, **kwargs): 
    if SwingUtilities.isEventDispatchThread(): 
     method(*args, **kwargs) 
    else: 
     SwingUtilities.invokeAndWait(RunnableClass(method, *args, **kwargs)) 
+0

감사합니다. 예, 이것은 깔끔한 기술이며 멋지게 비단뱀입니다. 나에게 일어난 아주 사소한 일은 여전히 ​​Runnable을 만들고 제출하는 것입니다. 나에게 일어난 다른 대안은 캡슐화 된 (파이썬) 대기열과 (Java) SwingWorker ...와 함께 (파이썬) 스레드 서브 클래스를 갖는 것입니다. 아주 잘 작동하고 성능 향상에 대해 전혀 모른다. 위의 코드를 넣었 으면 모든 주석을 환영 할 것입니다. –