Reputation: 699
I am trying to quit a thread after it is done processing. I am using moveToThread. I'm trying to quit the worker thread from the main thread by calling self.thread.quit() in the slot. And that's not working.
I've found several examples of starting the thread using moveToThread, such as this one. But I can't find how to quit one.
from PyQt5.QtCore import QObject, QThread
from PyQt5.QtCore import pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
print("Base init")
self.start_thread()
@pyqtSlot(int)
def onFinished(self, i):
print("Base caught finished, {}".format(i))
self.thread.quit()
print('Tried to quit thread, is the thread still running?')
print(self.thread.isRunning())
def start_thread(self):
self.thread = QThread()
self.w = Worker()
self.w.finished1[int].connect(self.onFinished)
self.w.moveToThread(self.thread)
self.thread.started.connect(self.w.work)
self.thread.start()
class Worker(QObject):
finished1 = pyqtSignal(int)
def __init__(self):
super().__init__()
print("Worker init")
def work(self):
print("Worker work")
self.finished1.emit(42)
if __name__ == "__main__":
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
This is the output from all my print functions (without the color of course):
Base init
Worker init
Worker work
Base caught finished, 42
Tried to quit thread, is the thread still running?
True
Upvotes: 4
Views: 3338
Reputation: 3033
same as answer above but showing option 2
that is using QThread.wait()
:
https://doc.qt.io/qtforpython/PySide6/QtCore/QThread.html#PySide6.QtCore.PySide6.QtCore.QThread.wait :
Blocks the thread until either of these conditions is met: The thread associated with this QThread object has finished execution (i.e. when it returns from run() ). This function will return true if the thread has finished. It also returns true if the thread has not been started yet. The deadline is reached. This function will return false if the deadline is reached. A deadline timer set to QDeadlineTimer::Forever (the default) will never time out: in this case, the function only returns when the thread returns from run() or if the thread has not yet started.
from PyQt5.QtCore import QObject, QThread
from PyQt5.QtCore import pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QMainWindow
import time
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
print("Base init")
self.start_thread()
@pyqtSlot(int)
def onFinished(self, i):
print("Base caught finished, {}".format(i))
self.thread.quit()
print('Tried to quit thread, is the thread finished ? : ', self.thread.isFinished())
print('Tried to quit thread, is the thread still running? : ', self.thread.isRunning())
# # option 1
# print( '\nafter time.sleep(2)')
# time.sleep(2)
# print('Tried to quit thread, is the thread finished ? : ', self.thread.isFinished())
# print('Tried to quit thread, is the thread still running? : ', self.thread.isRunning())
# option 2
self.thread.wait()
print( '\nafter thread.wait()')
print('Tried to quit thread, is the thread finished ? : ', self.thread.isFinished())
print('Tried to quit thread, is the thread still running? : ', self.thread.isRunning())
def start_thread(self):
self.thread = QThread()
self.w = Worker()
self.w.finished1[int].connect(self.onFinished)
self.w.moveToThread(self.thread)
self.thread.started.connect(self.w.work)
self.thread.start()
class Worker(QObject):
finished1 = pyqtSignal(int)
def __init__(self):
super().__init__()
print("Worker init")
def work(self):
print("Worker work")
self.finished1.emit(42)
if __name__ == "__main__":
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
output #option 1 sleep :
Base init
Worker init
Worker work
Base caught finished, 42
Tried to quit thread, is the thread finished ? : False
Tried to quit thread, is the thread still running? : True
after time.sleep(2)
Tried to quit thread, is the thread finished ? : True
Tried to quit thread, is the thread still running? : False
output #option 1 wait :
Base init
Worker init
Worker work
Base caught finished, 42
Tried to quit thread, is the thread finished ? : False
Tried to quit thread, is the thread still running? : True
after thread.wait()
Tried to quit thread, is the thread finished ? : True
Tried to quit thread, is the thread still running? : False
Upvotes: 0
Reputation: 5000
Try running your script multiple times. Is the result of the call to self.thread.isRunning()
always the same? Try adding a call to time.sleep(1)
before checking if the thread is still running. Notice any difference?
Remember that you are making a call from the main thread of your program, to another thread, which is by definition asynchronous. Your program will not wait to make sure self.thread.quit()
has completed before executing the next instructions.
Upvotes: 2