PyQt QThread:在线程仍在运行时被销毁

时间:2017-04-23 18:13:47

标签: python python-2.7 qt pyqt python-multithreading

尽管将QThread的引用保存为self.lightsThread,但停止QObject self.lightsWorker然后再次启动self.lightsThread会导致错误

QThread: Destroyed while thread is still running

停止self.lightsWorker后,QThread self.lightsThread也必须停止吗?如果没有,那似乎是什么问题?

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import time



class Screen(QMainWindow):
    def __init__(self):
        super(Screen, self).__init__()
        self.initUI()

    def initUI(self):
        self.lightsBtn = QPushButton('Turn On')
        self.lightsBtn.setCheckable(True)  
        self.lightsBtn.setStyleSheet("QPushButton:checked {color: white; background-color: green;}")
        self.lightsBtn.clicked.connect(self.lightsBtnHandler)

        self.setCentralWidget(self.lightsBtn)

    def lightsBtnHandler(self):
        if self.lightsBtn.isChecked():
            self.startLightsThread()
        else:
            self.stopLightsThread()

    def startLightsThread(self):
        print 'start lightsThread'
        self.lightsThread = QThread()
        self.lightsWorker = LightsWorker()
        self.lightsWorker.moveToThread(self.lightsThread)
        self.lightsThread.started.connect(self.lightsWorker.work)
        self.lightsThread.start()


    def stopLightsThread(self):
        print 'stop lightsThread'
        self.lightsWorker.stop()



class LightsWorker(QObject):
    signalFinished = pyqtSignal()

    def __init__(self):
        QObject.__init__(self)
        self._mutex = QMutex()
        self._running = True

    @pyqtSlot()
    def work(self):
        while self._running:
            print 'working'
            time.sleep(1)
        self.signalFinished.emit()

    @pyqtSlot()
    def stop(self):
        print 'Stopping'
        self._mutex.lock()
        self._running = False
        self._mutex.unlock()



app = QApplication(sys.argv)
window = Screen()
window.show()
sys.exit(app.exec_())

2 个答案:

答案 0 :(得分:4)

在停止instanceB后回答https://stackoverflow.com/a/32138213/7742341之后你应该从线程中退出并等待直到它被停止

lightWorker

答案 1 :(得分:2)

我不得不在C ++中遇到同样的问题,但问题是一样的。

问题是当关联的线程仍在运行时,您的QThread实例将被删除。这可能非常危险,因为线程代码执行被中断,而且保证线程已准备好被删除。

例如:

  • 线程控制对象(工人)的执行和生命时间
  • 在此对象析构函数中释放ressource(与使用QObject父/子系统时明显或不明确)
  • 由于线程执行被中断,因此不会删除该对象

导致内存泄漏和资源泄漏。

在您的代码中,工作程序已停止,但不是工作线程。我不是python专家,但似乎你的worker对象已停止但未被删除。

要正确停止您的工作人员和线程,您应该:

  • 向您的工作人员发送消息,告诉他们“停止工作”
  • 请求您的线程退出:它会向工作执行后将处理的线程发送“退出”消息
  • 等待你的帖子停止

最后一步是optionnal:如果线程和worker没有与其他对象共享资源,你可能不需要等待它们完成,只是忘记它们。

唯一的例外是在退出应用程序之前应该正确停止所有线程:您应该等待所有当前运行的线程在应用程序退出之前停止。

对于简单的任务,您还应该考虑使用QtConcurrent框架。