why am i getting QThread: Destroyed while thread is still running in this case?
-
With the below code, if you click start, a loop in qthread starts and when you click stop, it will terminate qthread by using ctypes. I know there are safer ways to terminiate qthread but since my actual code is way much longer than this, I think this method is better than other methods out there. The stop button works well for my intention but if I close gui, it will give me QThread: Destroyed while thread is still running. (even after the thread is terminated by using ctypes.pythonapi.PyThreadState_SetAsyncExc) I dont understand why I'm getting the error but I'm thinking ctypes.pythonapi.PyThreadState_SetAsyncExc doesnt actually terminate the thread but just pause the thread? I dont know.. It'd be very much appreciated if someone could tell me what I'm missing
import ctypes import sys import threading import time from PyQt5 import QtWidgets, QtCore from PyQt5.QtCore import QThread from PyQt5.QtWidgets import * class MyWindow(QMainWindow): def __init__(self): super().__init__() self.setupUi(self) self.Button_state = True self.pb_start.clicked.connect(self.click1_function) # thread setup self.test_thread_id = 0 def click1_function(self): if self.Button_state: self.Button_state = False self.pb_start.setText('Stop') self.test = Thread_Test1(self) self.test.daemon = True self.test.start() elif self.Button_state == False: self.Button_state = True self.pb_start.setText('start') self.test.stop_thread() print('check') def setupUi(self, QMainWindow): self.resize(500, 500) self.centralwidget = QtWidgets.QWidget(QMainWindow) self.centralwidget.setObjectName("centralwidget") self.pb_start = QtWidgets.QPushButton(self.centralwidget) self.pb_start.setGeometry(QtCore.QRect(100, 100, 100, 100)) self.pb_start.setObjectName("pb_start") self.pb_start.setText("Start") QMainWindow.setCentralWidget(self.centralwidget) class Thread_Test1(QThread): def __init__(self,parent): super().__init__(parent) self.parent = parent def run(self): i = 0 self.test_thread_id = int(self.currentThreadId()) while True: print(i) i += 1 time.sleep(1) print("END") print("End") def stop_thread(self): print (self.test_thread_id) res = ctypes.pythonapi.PyThreadState_SetAsyncExc(self.test_thread_id, ctypes.py_object(SystemExit)) if __name__ == "__main__": app = QApplication(sys.argv) myApp = MyWindow() myApp.show() app.exec_()
-
Hi,
Why are you using an external API to kill a QThread rather than use the API's provided by QThread ?
Also, on that front, never write an infinite loop that does not have an exit point. Killing thread is the least clean way to stop them. -
Hi,
Why are you using an external API to kill a QThread rather than use the API's provided by QThread ?
Also, on that front, never write an infinite loop that does not have an exit point. Killing thread is the least clean way to stop them.@SGaist said in why am i getting QThread: Destroyed while thread is still running in this case?:
Hi,
Why are you using an external API to kill a QThread rather than use the API's provided by QThread ?
I had the same reaction initially, but the python documentation has convinced me that this is actually a reasonable technique for long-running python blocks. It raises an exception (in this case, SystemExit - Request to exit from the interpreter) that may already be handled or at least more familiar to python developers. I don't know if this particular exception is the best choice.
Also, on that front, never write an infinite loop that does not have an exit point. Killing thread is the least clean way to stop them.
+1. For me, "killing a thread" is tantamount to an application crash, and should be treated as such. Any state the thread could have touched might be corrupted.