为啥在 macOS 上使用 QThread 时 PyQt 应用程序崩溃或挂起?
Posted
技术标签:
【中文标题】为啥在 macOS 上使用 QThread 时 PyQt 应用程序崩溃或挂起?【英文标题】:Why does PyQt application crash or hang when using QThread on macOS?为什么在 macOS 上使用 QThread 时 PyQt 应用程序崩溃或挂起? 【发布时间】:2020-11-18 23:55:03 【问题描述】:在 PyQt5 中调用线程类时,应用程序崩溃并出现错误:QThread: Destroyed while thread is still running 如果我不添加
def __del__(self):
self.wait()
将上述语句添加到线程类后,应用程序运行但停止,直到线程完成执行(基本上使线程无用)。我正在运行 macOS Catalina 10.15.6、Intel i9、Python 3.7.4。有什么办法可以解决这个问题?代码如下(ui窗口只有一个按钮):
from PyQt5.QtWidgets import QMainWindow
from PyQt5 import QtWidgets, uic
from PyQt5.QtCore import QThread, pyqtSignal
import sys, time
class Main(QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
uic.loadUi('main.ui', self)
self.btn1.clicked.connect(self.run_worker)
def run_worker(self):
worker = Worker_thread()
worker.start()
class Worker_thread(QThread):
def __init__(self):
QThread.__init__(self)
def __del__(self):
self.wait()
def run(self):
time.sleep(10)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
win = Main()
win.show()
sys.exit(app.exec_())
【问题讨论】:
在__del__
中添加self.wait()
是一个非常糟糕的主意。
@musicamante 能否详细说明原因?
有多种原因,包括您的情况(整个过程被阻塞直到完成,这意味着您可能需要杀死应用程序才能真正退出它,并且这不好)。此外,__del__
甚至可能根本不会被调用,清理这样的异步资源是不安全的,并且可能会在 C++ 对象已被销毁的情况下对 python 引用进行垃圾收集。阅读somerelevantquestions。
【参考方案1】:
问题很简单:“worker”变量是一个局部变量,当它的作用域结束时它会被消除,在这种情况下,作用域是“run_worker”函数。当“run”方法被淘汰时,它不是在管理QThread的辅助线程中执行,而是在阻塞GUI的主线程中执行。
解决方法是扩展其范围,例如通过制作类属性:
def run_worker(self):
self.worker = Worker_thread()
self.worker.start()
注意:问题与操作系统无关。
【讨论】:
以上是关于为啥在 macOS 上使用 QThread 时 PyQt 应用程序崩溃或挂起?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 ASP.NET-Core 应用程序会收到错误消息“此平台不支持锁定/解锁文件区域”。在 MacOS 上部署时?