如何正确终止GUI应用中的QThread?
我尝试在 QThread 类中使用 self.terminate()
,也在 GUI 类中使用 self.thread.terminate()
。我还尝试在这两种情况下都加上 self.wait()
。不过,有两种情况发生:
1) 线程根本没有结束,导致 GUI 界面卡住,等待线程完成。一旦线程结束,GUI 就恢复正常。
2) 线程确实结束了,但同时也让整个应用程序都卡住了。
我还尝试使用 self.thread.exit()
,但也没有成功。
为了更清楚,我想在 GUI 中实现一个用户中止按钮,可以随时终止正在执行的线程。
谢谢大家的帮助。
编辑:
这是 run()
方法:
def run(self):
if self.create:
print "calling create f"
self.emit(SIGNAL("disableCreate(bool)"))
self.create(self.password, self.email)
self.stop()
self.emit(SIGNAL("finished(bool)"), self.completed)
def stop(self):
#Tried the following, one by one (and all together too, I was desperate):
self.terminate()
self.quit()
self.exit()
self.stopped = True
self.terminated = True
#Neither works
这是 GUI 类中用于中止线程的方法:
def on_abort_clicked(self):
self.thread = threadmodule.Thread()
#Tried the following, also one by one and altogether:
self.thread.exit()
self.thread.wait()
self.thread.quit()
self.thread.terminate()
#Again, none work
3 个回答
我之前遇到过类似的问题,最后是通过使用 pyqtSignals
和 pyqtSlots
来解决的。你可以在你的主窗口类中创建一个 pyqtSignal
,并把 aboutToQuit
函数应用到你的 QApplication
实例上。然后,你把这个 aboutToQuit
函数连接到另一个函数,这个函数会发出一个信号给你在另一个线程中的槽函数。这样,你就可以在这个线程中定义一个 stop()
函数,当信号发出时这个函数就会运行。在这种情况下,线程在工作时就不会结束。
主窗口:
class mainSignals(QObject):
isClosed = pyqtSignal()
class mainwindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super(mainwindow, self).__init__()
self.mainSignal = mainSignals()
...
...
if __name__ = "__main__":
# This function runs if the application is closed.
# (app.aboutToQuit.connect(windowClose))
def windowClose():
window.mainSignal.isClosed.emit() # Emit the signal to the slot in (sepThread)
app = QApplication(sys.argv)
app.aboutToQuit.connect(windowClose)
window = mainwindow()
window.show()
sys.exit(app.exec())
分线程:
class sepThread(QRunnable):
def __init__(self, parent):
super(sepThread,self).__init__()
self._parent = parent
self.mainOpen = True
self._parent.mainSignal.isClosed.connect(self.stopThread)
# If the signal was emitted by the Mainapplication
# the stopThread function runs and set the mainOpen-attribute to False
def stopThread(self):
self.mainOpen = False
def run(self):
while self.mainOpen == True:
# Do something in a loop while mainOpen-attribute is True
...
...
我做了以下这些事情:
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
stop_flag = 1
...
#=========500 ms class ===================
class Timer500msThread(QThread):
signal_500ms = pyqtSignal(str)
....
def timer500msProcess(self):
if MainWindow.stop_flag == 0 :
self.timer_500ms.stop()
#==========
#=========Main Window ===================
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
MainWindow.stop_flag=0 #this sets the flag to 0 and when the next 500ms triggers the
#the thread ends
print("Program Ending")
来自Qt文档关于QThread::terminate的内容:
警告:这个函数很危险,不建议使用。你可以在任何时候终止一个线程,这样可能会导致线程在修改数据的时候被强行停止。这样的话,线程就没有机会自己清理,比如解锁任何被占用的资源等等。简单来说,只有在绝对必要的情况下才使用这个函数。
其实,重新考虑你的线程处理方式会更好,比如可以使用QThread::quit()来通知线程安全地退出,而不是用这种方式强行终止线程。实际上,如果你在线程内部调用thread.exit(),这应该可以实现安全退出,具体还要看你是如何实现run()方法的。如果你愿意分享一下你的线程运行方法的代码,可能能帮助找出为什么它不工作的原因。