2017-10-10 54 views
1

我在Windows上的PyQt中编写了一个GUI程序。我的程序中有一些昂贵的操作。在这些操作正在运行时,程序在程序栏中显示“Not Responding”。QThread Windows没有响应

我觉得一定是这个操作阻塞了主线程来更新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 
+0

你试过我的回答吗?如果您觉得它有用,请将其标记为已接受(即单击勾号符号)。 – ekhumoro

回答

0

您的程序有几个错误,并且不会生成您显示的输出。

首先,不可能将线程对象传递给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