在使用moveToThread时,如何正确退出PyQt5中的QThread

4

我试图在线程完成处理后退出它。我正在使用moveToThread。我尝试通过在槽中调用self.thread.quit()来从主线程退出工作线程。但是这不起作用。

我找到了几个使用moveToThread启动线程的示例,例如此示例。但我找不到如何退出线程。

from PyQt5.QtCore import QObject, QThread
from PyQt5.QtCore import pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QMainWindow

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        print("Base init")
        self.start_thread()

    @pyqtSlot(int)
    def onFinished(self, i):
        print("Base caught finished, {}".format(i))
        self.thread.quit()
        print('Tried to quit thread, is the thread still running?')
        print(self.thread.isRunning())

    def start_thread(self):
        self.thread = QThread()
        self.w = Worker()
        self.w.finished1[int].connect(self.onFinished)
        self.w.moveToThread(self.thread)
        self.thread.started.connect(self.w.work)
        self.thread.start()

class Worker(QObject):
    finished1 = pyqtSignal(int)

    def __init__(self):
        super().__init__()
        print("Worker init")

    def work(self):
        print("Worker work")
        self.finished1.emit(42)


if __name__ == "__main__":
    import sys
    from PyQt5.QtWidgets import QApplication

    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()

sys.exit(app.exec_())

这是所有打印函数的输出(当然不包括颜色):
Base init
Worker init
Worker work
Base caught finished, 42
Tried to quit thread, is the thread still running?
True
2个回答

2

尝试多次运行您的脚本。调用self.thread.isRunning()的结果是否总是相同的?在检查线程是否仍在运行之前,尝试添加对time.sleep(1)的调用。注意到了任何不同吗?

请记住,您正在从程序的主线程向另一个线程发出调用,这个线程按定义是异步的。在执行下一条指令之前,您的程序将不会等待确保self.thread.quit()已经完成。


1
谢谢!你是正确的。线程最终退出了。print(self.thread.isRunning())显示False。在添加time.sleep(1)后。 - squirtgun

0

与上面的答案相同,但显示选项2:

即使用QThread.wait()

https://doc.qt.io/qtforpython/PySide6/QtCore/QThread.html#PySide6.QtCore.PySide6.QtCore.QThread.wait

阻塞线程,直到满足以下任一条件: 与此QThread对象关联的线程已完成执行(即从run()返回)。如果线程已经完成,则此函数将返回true。如果线程尚未启动,则它也会返回true。 达到截止日期。如果达到截止日期,则此函数将返回false。 设置为QDeadlineTimer :: Forever(默认值)的截止定时器永远不会超时:在这种情况下,仅当线程从run()返回或线程尚未启动时,该函数才会返回。

from PyQt5.QtCore import QObject, QThread
from PyQt5.QtCore import pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QMainWindow

import time

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        print("Base init")
        self.start_thread()

    @pyqtSlot(int)
    def onFinished(self, i):
        print("Base caught finished, {}".format(i))
        self.thread.quit()
        print('Tried to quit thread, is the thread finished ? : ', self.thread.isFinished())
        print('Tried to quit thread, is the thread still running? : ', self.thread.isRunning())
        
        
        
        # # option 1
        # print( '\nafter time.sleep(2)')
        # time.sleep(2)
        # print('Tried to quit thread, is the thread finished ? : ', self.thread.isFinished())
        # print('Tried to quit thread, is the thread still running? : ', self.thread.isRunning())
        
        
        # option 2
        self.thread.wait()
        print( '\nafter thread.wait()')
        print('Tried to quit thread, is the thread finished ? : ', self.thread.isFinished())
        print('Tried to quit thread, is the thread still running? : ', self.thread.isRunning())
        
        
        
    def start_thread(self):
        self.thread = QThread()
        self.w = Worker()
        self.w.finished1[int].connect(self.onFinished)
        self.w.moveToThread(self.thread)
        self.thread.started.connect(self.w.work)
        self.thread.start()

class Worker(QObject):
    finished1 = pyqtSignal(int)

    def __init__(self):
        super().__init__()
        print("Worker init")

    def work(self):
        print("Worker work")
        self.finished1.emit(42)


if __name__ == "__main__":
    import sys
    from PyQt5.QtWidgets import QApplication

    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()

sys.exit(app.exec_())

输出 #选项 1 睡眠:

Base init
Worker init
Worker work
Base caught finished, 42
Tried to quit thread, is the thread finished ? :  False
Tried to quit thread, is the thread still running? :  True

after time.sleep(2)
Tried to quit thread, is the thread finished ? :  True
Tried to quit thread, is the thread still running? :  False

输出 #选项 1 等待:

Base init
Worker init
Worker work
Base caught finished, 42
Tried to quit thread, is the thread finished ? :  False
Tried to quit thread, is the thread still running? :  True

after thread.wait()
Tried to quit thread, is the thread finished ? :  True
Tried to quit thread, is the thread still running? :  False

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接