【问题标题】:PyQt Signals across threads跨线程的 PyQt 信号
【发布时间】:2017-05-10 13:00:24
【问题描述】:

我一直在搞乱 PyQt 和跨线程的信号/插槽。 这是我找不到错误的情况:

我有一个类 (MultipleProcessLauncher),它能够在单独的线程中启动多个进程。 我捕获每个进程的标准输出并将这些消息发送到由另一个线程(OutputWorker)读取的单个队列,最后一个线程应该发送一个信号 onNewMessage(我认为它没有)赶上主类,但从不调用回调函数。

  • 进程线程用消息填充队列
  • 阅读线程捕获所有这些消息(我可以在 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)

【问题讨论】:

  • 我认为item 不会是QString。您可能希望将信号定义更新为 pyqtSignal(str) 或类似名称。不知道这是否是问题的原因。
  • 如果我用 str 更改 QString 或者即使我没有在我的信号和插槽上放置任何参数,也不起作用

标签: python multithreading pyqt signals


【解决方案1】:

Qt 的跨线程信号是基于事件循环的,所以你需要执行一个 QApplication 以便有一个主事件循环来处理来自其他线程的信号。例如:

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()

在您的实际应用程序中,您可能会根据用户输入执行管理器,因此执行将在一个槽中,并且不需要退出等,但您明白了。

【讨论】:

    猜你喜欢
    • 2018-01-15
    • 2014-12-18
    • 1970-01-01
    • 1970-01-01
    • 2015-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    相关资源
    最近更新 更多