我使用的是PySide 1.2.2版,它包含了Qt v4.8框架。我处于这样一种情况,我必须选择让我的应用程序等待QThread
我不再需要正常退出(线程很可能会无限期地阻塞),并给予无响应的线程一个优雅句点(几秒钟),然后在其上调用QThread.terminate()
。虽然我希望我可以,但是当底层线程仍在运行时,我不能让QThread
对象超出范围,因为这会抛出错误“QThread:在线程仍在运行时被销毁”并且几乎肯定会导致段错误
请注意,我知道terminating QThread
s is dangerous and highly discouraged。我只是想在这里探讨我的选择。
但是当我尝试终止一个线程时,我的应用程序崩溃并出现以下错误:
致命的Python错误:释放
时,此线程状态必须是最新的
您可以通过复制/粘贴并运行以下代码来自行尝试:
from PySide import QtCore, QtGui
class Looper(QtCore.QThread):
"""QThread that prints natural numbers, one by one to stdout."""
def __init__(self, *args, **kwargs):
super(Looper, self).__init__(*args, **kwargs)
self.setTerminationEnabled(True)
def run(self):
i = 0
while True:
self.msleep(100)
print(i)
i += 1
# Initialize and start a looper.
looper = Looper()
looper.start()
# Sleep main thread for 5 seconds.
QtCore.QThread.sleep(5)
# Terminate looper.
looper.terminate()
# After calling terminate(), we should call looper.wait() or listen
# for the QThread.terminated signal, but that is irrelevant for
# the purpose of this example.
app = QtGui.QApplication([])
app.exec_()
如何在Python中正确终止QThreads?
我认为我得到的错误与发布Global Interpreter Lock有关,但我不确定到底出了什么问题,以及如何修复它。
答案 0 :(得分:2)
似乎错误可能是PySide特有的:用PyQt4运行你的例子根本不会产生任何错误。
至于如何安全地终止QThread
的一般问题:它完全取决于你对线程中正在完成的工作有多少控制权。如果它实际上是一个可以定期检查标志的循环,那么解决方案很简单:
class Looper(QtCore.QThread):
...
def interrupt(self):
self._active = False
def run(self):
i = 0
self._active = True
while self._active:
self.msleep(100)
print(i)
i += 1
app = QtGui.QApplication([])
looper = Looper()
looper.finished.connect(app.quit)
looper.start()
QtCore.QTimer.singleShot(3000, looper.interrupt)
app.exec_()
一旦run
方法返回,线程将干净地完成,因此您必须找到一些允许这种情况发生的机制。如果你不能这样做(也许是因为在线程中完成的工作基本上不在你的控制范围内),你应该考虑转而使用multiprocessing方法。