QThread does not Wait()

Maurizio Berti maurizio.berti at gmail.com
Fri Jul 2 03:30:59 BST 2021


I believe you're misunderstanding what "wait" does.

First of all, your loop will keep going since you're not telling it to stop
in any way: as the name says, wait() will only *wait* until the thread
associated with the QThread object has finished execution (as explained in
the documentation [1]).
Your thread will keep running until the condition of the while loop is met
(the counter has reached at least 101). Since the loop is time based, it
will exit only after the required amount of time.
Also, wait() is *blocking*, meaning that it won't return until the thread
has actually finished (causing the UI to freeze in the meantime). This is
obviously not what you're looking for.

If you have a continuous loop (a loop that cycles periodically at small
time intervals), you can use a simple flag:

    def long_running(self):
        self.counter = 0
        self.keepRunning = True
        while self.counter <= 100 and self.keepRunning:
            # ...

And then set that flag whenever you want to stop the thread:

    def WaitThread(self):
        self.obj.keepRunning = False

This is obviously the more simple way to do so, if the thread itself has
some blocking you need some timeout (for example, using a Queue with a
proper argument for get()) or an appropriate Queue result management in
order to exit the loop as soon as possible.

I *strongly* suggest you to carefully read the post from Giuseppe (and the
following thread) from your previous question, including all the provided
links, as I'm under the impression that you're still misunderstanding some
important aspects about multithreading (and I can understand that, as it's
a subject that often creates confusion).

That said, as a general suggestion, you should *not* name functions/methods
with starting uppercase letters. Only classes and constants use that
styling, and for a very good reason: it allows to clearly tell apart
classes/constants from variables/attributes, which is a very important
aspect in code readability.

Maurizio

[1] - https://doc.qt.io/qt-5/qthread.html#wait

Il giorno gio 1 lug 2021 alle ore 18:46 Demosthenes Koptsis <
demosthenesk at gmail.com> ha scritto:

> Hello, i test Qthread and i made an example with a Form, Run, Stop
> buttons and a progressbar.
>
> I want to click Run button and start a thread and to click Stop button
> and Wait the thread.
>
> I try to implement a movetothread example but the wait fails.
>
> Here is the code.
>
> MainWindow.py
>
> -------------------------
>
> # -*- coding: utf-8 -*-
>
> # Form implementation generated from reading ui file 'MainWindow.ui'
> #
> # Created by: PyQt5 UI code generator 5.15.4
> #
> # WARNING: Any manual changes made to this file will be lost when pyuic5 is
> # run again.  Do not edit this file unless you know what you are doing.
>
>
> from PyQt5 import QtCore, QtGui, QtWidgets
>
>
> class Ui_Form(object):
>      def setupUi(self, Form):
>          Form.setObjectName("Form")
>          Form.resize(400, 138)
>          self.btnRun = QtWidgets.QPushButton(Form)
>          self.btnRun.setGeometry(QtCore.QRect(20, 20, 89, 25))
>          self.btnRun.setObjectName("btnRun")
>          self.btnStop = QtWidgets.QPushButton(Form)
>          self.btnStop.setGeometry(QtCore.QRect(20, 60, 89, 25))
>          self.btnStop.setObjectName("btnStop")
>          self.progressBar = QtWidgets.QProgressBar(Form)
>          self.progressBar.setGeometry(QtCore.QRect(20, 100, 371, 23))
>          self.progressBar.setProperty("value", 24)
>          self.progressBar.setObjectName("progressBar")
>          self.dial = QtWidgets.QDial(Form)
>          self.dial.setGeometry(QtCore.QRect(200, 20, 50, 64))
>          self.dial.setObjectName("dial")
>          self.lcdNumber = QtWidgets.QLCDNumber(Form)
>          self.lcdNumber.setGeometry(QtCore.QRect(260, 20, 64, 71))
>          self.lcdNumber.setObjectName("lcdNumber")
>
>          self.retranslateUi(Form)
>          QtCore.QMetaObject.connectSlotsByName(Form)
>
>      def retranslateUi(self, Form):
>          _translate = QtCore.QCoreApplication.translate
>          Form.setWindowTitle(_translate("Form", "Test Thread"))
>          self.btnRun.setText(_translate("Form", "Run"))
>          self.btnStop.setText(_translate("Form", "Stop"))
>
>
> ----------------------------------------
>
>
> MoveToThread.py
>
> ----------------------------------------
>
> from PyQt5.QtWidgets import *
> from PyQt5.QtCore import *
> from MainWindow import *
> import sys
> import time
>
> class SomeObject(QObject):
>      finished = pyqtSignal()
>      changed = pyqtSignal(int)
>
>      def __init__(self, parent=None, counter_start=0):
>          super(SomeObject, self).__init__(parent)
>          self.counter = counter_start
>
>      def long_running(self):
>          self.counter = 0
>          while self.counter <= 100:
>              time.sleep(0.3)
>              self.counter += 1
>              self.changed.emit(self.counter)
>              print(str(self.counter))
>          self.finished.emit()
>
> class MainWindow(QWidget):
>      def __init__(self, parent=None):
>          super(MainWindow, self).__init__(parent)
>          self.ui = Ui_Form()
>          self.ui.setupUi(self)
>          self.center()
>          #Init progressBar
>          self.ui.progressBar.setValue(0)
>          #Buttons
>          self.ui.btnRun.clicked.connect(self.StartThread)
>          self.ui.btnStop.clicked.connect(self.WaitThread)
>          self.ui.dial.sliderMoved.connect(self.SetLCD)
>          #Init Thread
>          self.objThread = QThread()
>          self.obj = SomeObject()
>          self.obj.moveToThread(self.objThread)
>          self.obj.finished.connect(self.objThread.quit)
>          self.obj.changed.connect(self.SetProgressBarValue)
>          self.objThread.started.connect(self.obj.long_running)
>
>      def SetLCD(self):
>          self.ui.lcdNumber.display(self.ui.dial.value())
>
>      def WaitThread(self):
>          self.objThread.wait()
>
>      def StartThread(self):
>          self.objThread.start()
>
>      def SetProgressBarValue(self):
>          self.ui.progressBar.setValue(self.obj.counter)
>
>      def center(self):
>          # geometry of the main window
>          qr = self.frameGeometry()
>
>          # center point of screen
>          cp = QDesktopWidget().availableGeometry().center()
>
>          # move rectangle's center point to screen's center point
>          qr.moveCenter(cp)
>
>          # top left of rectangle becomes top left of window centering it
>          self.move(qr.topLeft())
>
> if __name__ == '__main__':
>      app = QApplication(sys.argv)
>      w = MainWindow()
>      #   Disable maximize window button
>      w.setWindowFlags(Qt.WindowCloseButtonHint |
> Qt.WindowMinimizeButtonHint)
>      w.show()
>      sys.exit(app.exec_())
> ----------------------------------------------
>
> When i call WaitThread the emit of counter stops but the while loop
> works after all
>
>

-- 
È difficile avere una convinzione precisa quando si parla delle ragioni del
cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20210702/3ef32a1e/attachment-0001.htm>


More information about the PyQt mailing list