【问题标题】:PyQt – Signal for object created in different thread doesn't workPyQt – 在不同线程中创建的对象的信号不起作用
【发布时间】:2026-01-28 06:00:01
【问题描述】:

我正在 PyQt5 和 Python 3.5 中通过在 QThread 中运行 Worker 来实现多线程。在以下示例中,thread2_worker(在辅助线程中运行并)创建thread3_worker,将thread3_worker.finished 信号连接到thread3_worker_finished() 并运行它。

thread3_worker 完成时,它会在其线程内发出finished,但连接不起作用。我的猜测是它与thread3_worker 不是在主线程中创建或连接有关,但我欢迎任何澄清。

import time
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot, QCoreApplication


class Worker(QObject):
    # Generic worker.
    finished = pyqtSignal()

    def __init__(self, func):
        super().__init__()
        self.func = func

    def run(self):
        self.func()
        self.finished.emit()


def thread_factory(func):
    # Creates a Worker, a QThread and moves the Worker inside the QThread.
    worker = Worker(func)
    thread = QThread()
    worker.moveToThread(thread)
    thread.started.connect(worker.run)

    # Provision graceful termination.
    worker.finished.connect(thread.quit)
    worker.finished.connect(worker.deleteLater)
    thread.finished.connect(thread.deleteLater)

    return worker, thread


def wait():
    print("thread3:\t{}".format(QThread.currentThread()))
    time.sleep(3)


# finished signal of thread3_worker is never received.
@pyqtSlot()
def thread3_worker_finished():
    QCoreApplication.exit()


def create_thread3():
    print("thread2:\t{}".format(QThread.currentThread()))
    global thread3_worker, thread3
    # thread3_worker runs inside thread3, and all it does is call wait().
    thread3_worker, thread3 = thread_factory(wait)
    thread3_worker.finished.connect(thread3_worker_finished)  # FIXME Doesn't work.
    thread3.start()


app = QCoreApplication([])
print("Main thread:\t{}".format(QThread.currentThread()))
thread3_worker, thread3 = None, None
# thread2_worker runs inside thread2, and creates and runs thread3_worker.
thread2_worker, thread2 = thread_factory(create_thread3)
thread2.start()
app.exec_()

【问题讨论】:

    标签: python multithreading pyqt5 signals-slots qthread


    【解决方案1】:

    跨线程信号需要一个事件循环。您的thread_factory 函数将worker 的finished 信号连接到其线程的quit 插槽。 quit 槽要求线程退出其事件循环。

    所以在thread3启动后,worker2结束,thread2退出。然后当 worker3 的finished 信号发出时,不再有一个事件循环运行可以处理它。如果您注释掉 worker.finished.connect(thread.quit) 行,您的示例应该可以工作。

    【讨论】:

    • 事实上,注释掉worker.finished.connect(thread.quit) 修复了它。感谢您分享您的专业知识。我以为每个 QThread 都有自己的事件循环。
    • @R01k。每个线程确实 有它自己的事件循环。但是worker3需要thread2的事件循环(因为信号是跨线程发出的)。
    • 由于线程事件循环在其worker完成后继续进行,thread.deleteLater()最终是否仍然删除线程?
    最近更新 更多