Почему QThread ведет себя иначе, если создает его как локальную переменную - PullRequest
0 голосов
/ 23 ноября 2018

Я обнаружил странное поведение, если я создаю QThread как локальную переменную.

Например, следующий код будет работать как один поток, что означает, что мне нужно подождать 10 секунд, и результат будет получен.

Но если я изменю поток с локальной переменной на переменную-член, он работает как многопоточный.

Как дела?Кто-нибудь может дать мне несколько советов?

class UI():
    def __init__(self):
        self.app = QtGui.QApplication(sys.argv)
        self.dialog = QtGui.QDialog()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self.dialog)
        self.ui.btn.clicked.connect(self.btnclick)

    def run(self):
        self.dialog.show()
        sys.exit(self.app.exec_())

    def btnclick(self):
        ## if change to self.thread, the behavior changes!!
        signal = QtCore.SIGNAL("Log(QString)")
        thread = testThread(signal)  
        QtCore.QObject.connect(thread, signal, self.output)
        thread.start()

    def output(self, txt):
        self.ui.logText.append(str(txt))

class testThread(QThread):
    def __init__(self, signal):
        QThread.__init__(self)
        self.signal = signal

    def __del__(self):
        self.wait()

    def run(self):
        for i in range(10):
            time.sleep(1)
            self.output(str(i))

    def output(self, txt):
        self.emit(self.signal, txt)


if __name__ == "__main__":
    ui = UI()
    ui.run()

1 Ответ

0 голосов
/ 26 ноября 2018

Проблема заключается в том, что это локальная переменная, которая будет уничтожена через мгновение после запуска QThread, поэтому поток, который обрабатывается QThread (QThread не является потоком, это потокобработчик) будет удален, и при использовании wait() ожидается, что метод run() будет выполнен, но в основном потоке, генерирующем зависание графического интерфейса.

Таким образом, решение состоит в том, чтобы продлить срок жизни переменнойПоток, один из способов указать, что он работает: сделать его членом класса, но есть другой способ, который работает только с QObjects как QThread и заключается в передаче родителя (родитель должен быть другим QObject), который будет расширятьсясрок службы объекта до той же емкости, что и у родителя, поэтому я буду использовать диалоговое окно.

Наконец, в настоящее время не рекомендуется создавать сигналы динамически, лучше создавать его как часть классаТакже для соединения необходимо использовать новый синтаксис .

class UI():
    def __init__(self):
        self.app = QtGui.QApplication(sys.argv)
        self.dialog = QtGui.QDialog()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self.dialog)
        self.ui.btn.clicked.connect(self.btnclick)
        self.dialog.show()

    def btnclick(self):
        thread = testThread(self.dialog)  
        thread.signal.connect(self.output)
        thread.start()

    def output(self, txt):
        self.ui.logText.append(str(txt))

class testThread(QtCore.QThread):
    signal = QtCore.pyqtSignal(str)

    def __del__(self):
        self.wait()

    def run(self):
        for i in range(10):
            QtCore.QThread.sleep(1)
            self.output(str(i))

    def output(self, txt):
        self.signal.emit(txt)

if __name__ == '__main__':
    ui = UI()
    app = QtGui.QApplication.instance()
    if app is not None:
        sys.exit(app.exec_())
...