0

Addressing concerns of "duplicate question" - thank you for properly reading my question:

  1. Cannot terminate PyQT QThread - Uses terminate(), something I clearly said that I do not want to use because it is not safe
  2. How to stop QThread "gracefully"? - Uses a flag, something I clearly said that I do not want to use because the real application is not a simple loop
  3. Stopping an infinite loop in a worker thread in PyQt5 the simplest way - The real application is not a simple loop

Find below a simple full working example of a problem I am facing. I am trying to figure out how to properly use QThreads, and following some common advice I am using the moveToThread function. However, despite this, when I call quit on the thread, it seemingly does not do anything (it keeps printing).

import sys
import time
from PySide6.QtCore import QThread, Signal, QEventLoop, QObject
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton

class Worker(QObject):
    finished = Signal()

    def long_task(self):
        i=0
        while i<1000:
            i+=1
            print("Hello World")
            time.sleep(1)

        self.finished.emit()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PySide6 Thread Example")
        self.setGeometry(100, 100, 300, 200)

        self.button = QPushButton("Stop Thread", self)
        self.button.setGeometry(100, 100, 100, 50)
        self.button.clicked.connect(self.stop_thread)


        self.thread1 = QThread(self)
        self.worker = Worker()
        self.worker.moveToThread(self.thread1)

        self.thread1.started.connect(self.worker.long_task)
        self.worker.finished.connect(self.thread1.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread1.finished.connect(self.thread1.deleteLater)

        self.thread1.start()


    def stop_thread(self):
        self.thread1.exit()
        # self.thread1.quit()


app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

Pressing the button will not stop the worker. Is there a way to make this work under the following conditions?

  1. Without using terminate()
  2. Without using flags
  3. Without using "short tasks" (what is the point of exit then, if you have to wait for the work to be done anyway?)

I am guessing I am doing something wrong - or maybe I am following the complete wrong approach.

Modo
  • 53
  • 5
  • The docs are quite clear on the point. [`quit()`](https://doc.qt.io/qt-6/qthread.html#quit): "Tells the thread's event loop to exit with return code 0 (success). Equivalent to calling QThread::exit(0)." [`exit()`](https://doc.qt.io/qt-6/qthread.html#exit): "Tells the thread's event loop to exit with a return code.". Calling any of them just ***tells*** the event loop of that thread to exit. But your `long_task` function is blocking the event loop to process any event (including *exiting*) or be aware of its conclusion. Just check an internal flag within the loop that is run within the thread. – musicamante Jul 07 '23 at 01:43
  • @musicamante Unfortunately, using a flag (as I have clearly mentioned in the post) is not a solution that I want to use. That is because in the real application it is not a simple loop. I think the real answer to my question is: it is not possible – Modo Jul 07 '23 at 02:12
  • Sorry, I missed that part. Still, that's one of the *few* ways to gracefully exit a function running a thread. And, actually, it makes sense: fundamentally speaking, you're actually trying to *exit* a function before it has completed. Conceptually speaking, if that function doesn't explicitly allow termination, you're not allowed to do that in any way. Even without considering threading, how would you do that? In fact, you're completely excluding *any* way of actually terminating that function: no flag, no check, not even an abrupt thread termination, even considering that it wouldn't be safe. – musicamante Jul 07 '23 at 02:31
  • The real question here is: what does that thread **actually** do? Why can't it be stopped? These are fundamental questions you failed to explain in your post and may (possibly) provide ways to a solution, a work around or, at least, a *clear and valid* negative answer. Your code is fine for the *reproducibility* aspect, but it's completely insufficient to understand underlying requirements of your request. Please try to improve your question and clarify the needs of those specific requests, otherwise you'll have to surrender to that "is not possible", which may be true, as much as it may not. – musicamante Jul 07 '23 at 02:35

0 Answers0