QThread Windows 没有响应

QThread Windows not responding

我在 Windows 上用 PyQt 写了一个 GUI 程序。我的程序中有一些昂贵的操作。虽然这些操作是 运行ning,但程序在程序栏中显示 "Not Responding"。

我想肯定是这个操作阻塞了主线程去更新UI,所以我用QThread写了多线程代码测试了一下,还是不行。

我写了一个小程序来测试,在新线程中根本没有运行运行,这是我的小测试代码:

from PyQt5.QtCore import QThread, QObject, QCoreApplication, qDebug, QTimer


class Worker(QObject):
    def on_timeout(self):
        qDebug('Worker.on_timeout get called from: %s' % hex(int(QThread.currentThreadId())))


if __name__ == '__main__':
    import sys

    app = QCoreApplication(sys.argv)
    qDebug('From main thread: %s' % hex(int(QThread.currentThreadId())))
    t = QThread()
    qDebug(t)
    worker = Worker()
    timer = QTimer()
    timer.timeout.connect(worker.on_timeout)
    timer.start(1000)
    timer.moveToThread(t)
    worker.moveToThread(t)
    t.start()

    app.exec_()

这是输出:

From main thread: 0x634
Worker.on_timeout get called from: 0x634

您的程序有几个错误,无法产生您显示的输出。

首先,无法将线程对象传递给 qDebug - 参数必须是字符串。如果要打印对象,请使用 qDebug(repr(obj)) - 或者更好,只需使用 print(obj).

其次,您不能在创建计时器的线程之外启动计时器。您的示例在主线程中建立信号连接,并在主线程中启动计时器。所以worker.on_timeout会在主线程中被调用。但是如果你在 将它移动到工作线程之后连接并启动定时器 ,你将得到这个错误:

QObject::startTimer: Timers can only be used with threads started with QThread

我认为使用定时器是不必要的,并且会混淆你的例子,所以最好完全不使用它。相反,您应该将工作线程的 started 信号连接到工作对象的 run 方法。要模拟长运行操作,可以使用QThread.sleep():

from PyQt5.QtCore import QThread, QObject, QCoreApplication

class Worker(QObject):
    def run(self):
        print('Worker called from: %#x' % int(QThread.currentThreadId()))
        QThread.sleep(2)
        print('Finished')
        QCoreApplication.quit()

if __name__ == '__main__':

    import sys
    app = QCoreApplication(sys.argv)
    print('From main thread: %#x' % int(QThread.currentThreadId()))
    t = QThread()
    worker = Worker()
    worker.moveToThread(t)
    t.started.connect(worker.run)
    t.start()
    app.exec_()

最后,请注意,在将工作对象移动到线程后,您应该始终建立信号连接。 this answer.

中解释了其原因