如何正确退出 Pyside2 多线程 GUI 应用程序?
Posted
技术标签:
【中文标题】如何正确退出 Pyside2 多线程 GUI 应用程序?【英文标题】:How to properly exit from Pyside2 multi-thread GUI application? 【发布时间】:2021-01-09 14:28:42 【问题描述】:我正在使用 pyside2 并编写了一个应用程序,其中有几个线程使用队列在它们之间进行通信。一个线程从串行端口读取数据并将数据传递给另一个线程,该线程解析它们并在绘图之前进行一些计算。从我的 app_main.py 文件中:
import sys
# omissis various import statements
class MainWindow(QMainWindow, Ui_MainWindow):
serialRxQu = Queue() # serial FIFO RX Queue
serialWo = ""
def __init__(self, *args, **kwargs):
Ui_MainWindow.__init__(self)
QMainWindow.__init__(self)
# omissis, various ui initializations
# Visualization Worker Thread, started as soon as the thread pool is started.
self.viewWo = ViewWorker(self.serialRxQu, self.canvas, self.textEdit)
# serial Worker Thread started later
self.serialWo = SerialWorker(self.serialRxQu, self.textEdit)
self.threadpool = QThreadPool()
self.threadpool.start(self.viewWo)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
我省略了一些对问题无用的部分,如果不包含其他文件,它们将难以解释。
应用程序 exec 是使用 `sys.exit(app.exec_()) 调用的,据我了解,这意味着当我关闭应用程序的主窗口时,事件调度程序将关闭并传递返回代码到 sys.exit 应该终止应用程序的执行。
我尝试使用命令python app_main.py
从 Windows 中的命令行启动应用程序,我看到的是,当我关闭应用程序的主窗口时,进程似乎挂在终端中,我从来没有得到提示返回。
我还尝试将sys.exit()
与app.exec_()
分开,如下所示:
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
style_man = StyleManager(app)
window = MainWindow()
window.show()
# sys.exit(app.exec_())
app.exec_()
print("I pass here!")
sys.exit(0)
我在终端上看到了 I pass here!
的打印字样,但在这种情况下,我再也没有收到提示。我确实希望sys.exit()
调用会终止进程,但也许有一些东西挂起并阻止应用程序关闭?
可能是事件调度程序仍在运行吗?或者任何与线程或队列相关的东西?
还是我应该使用不同于sys.exit()
的东西?
我希望能正确解释我的情况和我的疑问,否则我会尝试纠正我的问题。
【问题讨论】:
【参考方案1】:经过一些故障排除后,我认为我发现了我的程序的问题。
对于线程,我使用从 QRunnable 派生的对象,线程是无限循环,一个监听串行,另一个在新数据到达时绘制数据。
作为无限循环,线程继续运行,并且由于它们每个人都有一个计时器对象,因此计时器对象可能会阻止执行调度程序终止。
为了解决这个问题,我在线程循环中添加了一个标志并使用了应用程序的关闭事件
def closeEvent(self, event):
self.set_finish_signal()
app.exit(0)
def set_finish_signal(self):
self.viewWo.terminate_thread()
self.serialWo.terminate_thread()
运行循环条件在启动时始终为 False,terminate_thread 函数将信号更改为 True 并且 Run 终止,释放计时器资源并允许执行正确终止。
【讨论】:
以上是关于如何正确退出 Pyside2 多线程 GUI 应用程序?的主要内容,如果未能解决你的问题,请参考以下文章
如何从具有 PySide2 GUI 的 python 脚本构建一个 mac os 应用程序?
PySide2:不能在不退出 APP 的情况下关闭 QMessageBox