2016-12-25 9 views
4

私はPyQtとシグナル/スロットをスレッド間で使いこなしてきました。私は私のミスを見つけることができません ここで状況:PyQtスレッド間のシグナル

は、私は別のスレッドで複数のプロセスを起動することができますクラス(MultipleProcessLauncher)を持っています。 私は各プロセスのstdoutをキャッチし、別のスレッド(OutputWorker)によって読み取られる単一のキューにそれらのメッセージを送信します。この最後のスレッドは、メインクラスをキャッチするNewMessage(私はそう思わない)コールバック関数が呼び出されることはありません。 - 信号 :プロセスのスレッドが読み取り糸捕獲にメッセージ

  • ですべてのそれらのメッセージ(私はwhileループでprint(item)でそれらを印刷することができます)
  • しかしをキューに移入

    • 読み込みスレッドの中には何も出されていないようですので、メインスレッドのコールバック関数は呼び出されません。

      あなたの助けには大いに感謝します。私は...私は、クロススレッド信号に何かが欠けていると思う

      class OutputWorker(QObject): 
          onNewMessage = pyqtSignal(['QString']) 
      
          def __init__(self, queue, parent=None): 
           super(OutputWorker, self).__init__(parent) 
           self.queue = queue 
      
          def work(self): 
           while True: 
            item = self.queue.get() 
            self.onNewMessage.emit(item) 
            self.queue.task_done() 
      
      class MultipleProcessLauncher(QObject): 
          commandEvent = pyqtSignal(['QString']) 
      
          def __init__(self, parent=None): 
           super(MultipleProcessLauncher, self).__init__(parent) 
      
           self.messaging_queue = Queue() 
      
           # Start reading message 
           self.reading_thread = QThread() 
      
           self.worker = OutputWorker(self.messaging_queue) 
           self.worker.moveToThread(self.reading_thread) 
           self.worker.onNewMessage.connect(self.command_event) 
      
           self.reading_thread.started.connect(self.worker.work) 
           self.reading_thread.start() 
      
          def execute(self, command): 
           p = subprocess.Popen(command, stdout=subprocess.PIPE) 
           t = Thread(target=self.enqueue, args=(p.stdout, self.messaging_queue)) 
           t.daemon = True 
           t.start() 
      
          def enqueue(self, stdout, queue): 
           for line in iter(stdout.readline, b''): 
            queue.put(line.decode()) 
           stdout.close() 
      
          def command_event(self, event): 
           # This point is never reached 
           print('message received') 
      
      if __name__ == '__main__': 
          manager = MultipleProcessLauncher() 
          manager.execute('ipconfig') 
      
          time.sleep(100) 
      
    +0

    'item'は' QString'とは思えません。シグナル定義を 'pyqtSignal(str)'などに更新したいかもしれません。それが問題の原因であるかどうかは確かではありません。 –

    +0

    QStringをstrで変更した場合や、シグナルとスロットに引数を入れなかった場合でも動作しません。 – And0rian

    答えて

    3

    Qtのクロススレッドのシグナリングはイベントループに基づいて、あなたは信号を処理するためのメインイベントループがあるようにはQApplicationをexecしする必要がありますされます他のスレッドから。たとえば:

    if __name__ == '__main__': 
        app = QApplication([]) 
        manager = MultipleProcessLauncher() 
        manager.execute('ipconfig') 
        MAX_WAIT_MSEC = 100 * 1000 # 100 seconds 
        QTimer.singleShot(MAX_WAIT_MSEC, app.quit) 
        app.exec() 
    

    あなたの実際のアプリケーションでは、おそらくスロットになり、実行、およびなど終了する必要が、そこではありませんので、ユーザーの入力に基づいて管理を実行しますが、あなたが得ますアイディア。

    +0

    あなたは正しいです! – And0rian

    関連する問題