2017-10-10 79 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