Python-PyQt:重新启动已完成的线程

时间:2018-10-09 08:12:47

标签: python multithreading pyqt pyqt5 qthread

我有pyqt接口,如果按下按钮,它将启动QThread。线程运行,完成后,我可以再次启动它,到目前为止没有问题。 现在,我添加了一个用于连续操作线程的复选框。如果选中了该复选框,则该按钮将保持按下状态,并且必须再次按下该按钮以停止线程。

显然,在停止之后,线程已正确完成(也使用isRunning()方法进行了检查),但是如果我尝试在连续操作中再次启动它,则程序将崩溃。如果我改为在连续操作关闭的情况下重新启动它,则不会发生这种情况,但是在这种情况下,线程被启动和停止了两次。

如何解释这种行为?有没有办法使其按预期工作?

一个例子:

import sys
from PyQt5 import QtCore
import PyQt5.QtWidgets as QtW
from PyQt5.QtCore import QThread, pyqtSlot, pyqtSignal
import time

class MyWindow(QtW.QMainWindow):

  def __init__(self):
    super().__init__()
    self.setWindowTitle('MyWindow')
    self._main = QtW.QWidget()
    self.setCentralWidget(self._main) 
    self.button = QtW.QPushButton('Do it', self)
    self.button.clicked.connect(self.do)
    self.contincheck = QtW.QCheckBox("Continuous")
    self.contincheck.clicked.connect(self.continuous_doing)
    self.continuous = False
    self.layout = QtW.QGridLayout(self._main)
    self.layout.addWidget(self.button,0,0)
    self.layout.addWidget(self.contincheck,1,0)
    self.setLayout(self.layout)
    self.show()

  def continuous_doing(self):
    if self.contincheck.isChecked():
      self.button.setCheckable(True)
      self.continuous = True
    else:
      self.button.setCheckable(False)
      self.continuous = False

  def do(self):
    if self.button.isCheckable() and not self.button.isChecked():
        self.button.setText('Do it')
        self.button.clicked.connect(self.do)
        self.contincheck.setEnabled(True)
    else:
        self.mythread = MyThread(self.continuous)
        if self.button.isCheckable() and self.button.isChecked():
            self.button.setText('Stop doing that')
            self.contincheck.setDisabled(True)
            self.button.clicked.connect(self.mythread.stop)
        self.mythread.finished.connect(self.thread_finished)
        self.mythread.signal.connect(self.done)
        self.mythread.start()

  @pyqtSlot(int)
  def done(self, i):
      print('done it', i)

  @pyqtSlot()
  def thread_finished(self):
      print('thread finished')



class MyThread(QThread):
    signal = pyqtSignal(int)

    def __init__(self, continuous):
        QThread.__init__(self)
        self._stopped = True
        self.continuous = continuous
        self.i = 0

    def __del__(self):
        self.wait()

    def stop(self):
        self._stopped = True

    def run(self):
        self._stopped = False
        while True:
            self.signal.emit(self.i)
            if self._stopped:
                break
            if self.continuous: time.sleep(2)
            else: break


if __name__ == '__main__':
    app = QtCore.QCoreApplication.instance()
    if app is None:
        app = QtW.QApplication(sys.argv)
    mainGui = MyWindow()
    mainGui.show()
    app.aboutToQuit.connect(app.deleteLater)
    app.exec_()

1 个答案:

答案 0 :(得分:0)

问题在于您正在创建一个新线程,而不是重用现有线程,在下面的示例中,我向您展示了如何正确地进行操作:

Entries