【问题标题】:Trying to stop a QThread gracefully, what's wrong with this implementation?试图优雅地停止 QThread,这个实现有什么问题?
【发布时间】:2016-08-10 21:15:18
【问题描述】:

在运行我的代码时,我会启动一个运行大约 50 秒的线程并执行大量后台操作。如果我运行这个程序然后很快关闭它,这些东西仍然会在后台运行一段时间,因为线程永远不会死。如何在我的 MianWindow 类的 closeEvent 方法中优雅地终止线程?我尝试设置一个名为 exit() 的方法,在相关线程中创建一个信号“quitOperation”,然后尝试使用

myThread.quitOperation.emit()

我希望这会在我的线程中调用我的 exit() 函数,因为我的构造函数中有这一行:

self.quitOperation.connect(self.exit)

但是,当我使用第一行时,它会中断,说“myThread”没有属性“quitOperation”。为什么是这样?有没有更好的办法?

【问题讨论】:

  • 请显示定义你的线程类的代码(包括信号定义)
  • 一般来说,提供 SSCCE 会带来更快的帮助:解决一个最小的完整工作示例要容易得多。见sscce.org

标签: python multithreading pyqt pyqt4 qthread


【解决方案1】:

我不确定python,但我假设这个myThread.quitOperation.emit() 发出一个信号让线程退出。关键是,当您的工作人员正在使用线程并且没有返回或运行QCoreApplication::processEvents() 时,myThread 将永远没有机会实际处理您的请求(这称为线程饥饿)。

正确答案可能取决于具体情况,以及您的线程正在做的“事情”的性质。最常见的做法是主线程向插槽设置标志的工作线程发送信号。在阻塞过程中,您会定期检查此标志。它设置你停止你正在做的任何“东西”,告诉你的工作线程它可以退出(最好使用排队连接的信号),在工作对象本身上调用deleteLater(),然后从你的任何函数返回当前在,以便线程的事件处理程序可以运行,并清除您的工作对象和自身,最终退出。

如果你的“东西”是一个非常快速的操作的巨大循环,比如简单的数学运算或逐个目录导航,每个只需要几毫秒,这就足够了。

如果你的“东西”包含你无法控制的巨大阻塞部分(因此你不能在其中放置这个标志检查调用),你可能需要在主线程中等待,直到工作线程退出。

如果您使用直接连接设置标志,或者您直接设置,请务必使用QMutex 保护标志的读/写访问以防止不一致的读取,或使用排队连接以确保单一标志的线程访问。

虽然非常不鼓励,但您可以选择使用QThreadterminate() 方法来立即终止线程。切勿这样做,因为它可能会导致内存泄漏、堆损坏、资源泄漏和任何令人讨厌的东西,因为析构函数和清理代码将无法运行,并且可能会在不希望的状态下停止执行。

【讨论】:

    猜你喜欢
    • 2021-06-04
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    • 2011-09-08
    • 2018-09-27
    相关资源
    最近更新 更多