QThread Windows not responding

I wrote a GUI program in PyQt on Windows. There's some expensive operations in my program. While these operations are running, the program shows "Not Responding" in the program bar.

I think it must be this operation block the main thread to update the UI, so I write multi-threading code by QThread to test it, it still not make sense.

I wrote a small program to test it, the operation did not run in new thread at all, here is my small test code:

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

Here is the output:

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

Your program has several errors and does not produce the output that you show.

Firstly, it is not possible to pass a thread object to qDebug - the argument must be a string. If you want to print objects, use qDebug(repr(obj)) - or even better, just use print(obj) .

Secondly, you cannot start a timer outside of the thread that created it. Your example makes the signal connection in the main thread, and starts the timer in the main thread as well. So worker.on_timeout will be called in the main thread. But if you connect and start the timer after moving it to the worker thread, you will get this error:

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

I think using a timer is unnecessary, and confuses your example, so it is better to leave it out altogether. Instead, you should connect the started signal of the worker thread to a run method of the worker object. To simulate a long-running operation, you can use 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_()

Finally, note that you should always make signal connections after moving a worker object to a thread. The reasons for this are explained in this answer.

链接地址: http://www.djcxy.com/p/64498.html

上一篇: 无法让Firefox或IE尊重最大

下一篇: QThread Windows没有响应