问题
I am new to PySide2. I am just trying to launch a sample application and start a thread as the application starts and want to stop the thread as the application closes. When I am closing the application I am getting the following error: QThread: Destroyed while the thread is still running. The sample_ui.py is a python file that I converted from sample_ui.ui
Code:
import time
import sys
import sample_ui
from PySide2 import QtWidgets
from PySide2 import QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
main_window_ui = sample_ui.Ui_MainWindow()
main_window_ui.setupUi(self)
self.custom_thread = CustomThread()
self.custom_thread.start()
def closeEvent(self, event):
self.custom_thread.stop()
QtWidgets.QMainWindow.closeEvent(self, event)
class CustomThread(QtCore.QThread):
def __init__(self):
super(CustomThread, self).__init__()
def run(self):
while self.isRunning():
print("Thread is Running")
time.sleep(1)
def stop(self):
print("Thread Stopped")
self.quit()
if __name__ == '__main__':
app = QtWidgets.QApplication()
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
Output:
Thread is Running
Thread is Running
Thread is Running
Thread Stopped
QThread: Destroyed while thread is still running
回答1:
Explanation:
By default the QThread run() method has the following implementation:
// https://github.com/qt/qtbase/blob/5.14.1/src/corelib/thread/qthread.cpp#L601
void QThread::run()
{
(void) exec();
}
In other words, the run method executes an event loop but when override that method you are removing the event loop by the while loop.
On the other hand if the Qt docs is reviewed:
void QThread::quit()
Tells the thread's event loop to exit with return code 0 (success). Equivalent to calling QThread::exit(0).
This function does nothing if the thread does not have an event loop.
(emphasis mine)
So if there is no event loop then the quit method will do nothing.
Solution:
A possible solution is to use isInterruptionRequested() and requestInterruption() since the first one indicates the state of the flag and the second one changes the state of that flag. On the other hand you have to wait for the thread to finish executing using the wait() method:
class CustomThread(QtCore.QThread):
def run(self):
while not self.isInterruptionRequested():
print("Thread is Running")
time.sleep(1)
def stop(self):
print("Thread Stopped")
self.requestInterruption()
self.wait()
回答2:
QThread::quit()
does nothing if your thread doesn't have an event loop. You should use a flag that "turns off" the while
inside your run()
instead of checking what QThread::isRunning()
returns. In addition it is advisable to always add a QThread::wait()
with a specific time limit and then add (as a backup plan) a QThread::terminate()
.
Just as an experiment add a check for QThread::isRunning()
after you call your stop()
function and see what it returns.
来源:https://stackoverflow.com/questions/60124633/pyside2-qthread-error-qthread-destroyed-while-thread-is-still-running