完成后如何自动退出PyQT QThread?

Posted

技术标签:

【中文标题】完成后如何自动退出PyQT QThread?【英文标题】:How to quit PyQT QThread automatically when it is done? 【发布时间】:2019-11-08 15:38:20 【问题描述】:

我希望在 PyQT5 中单击按钮时播放声音。

播放声音似乎是一个阻塞操作,因此 GUI 没有响应。因此,我想以非阻塞方式启动一个新线程、播放声音和删除线程。

我创建了一个线程类

class playSoundThread(QtCore.QThread):
    def __init__(self, soundpath):
        QtCore.QThread.__init__(self)
        self.soundpath = soundpath

    def __del__(self):
        self.wait()
        print("Thread exited")

    def run(self):
        playsound(self.soundpath)

然后运行如下

class MainClass(...):
    ...

    def playsound(self, soundKey):
        self.thisSoundThread = playSoundThread(self.sounds[soundKey])
        self.thisSoundThread.start()

一切正常且无阻塞。唯一的问题是当声音停止播放时线程不会被删除。我试过打电话给del self.thisSoundThread,但是这个操作似乎是阻塞的,打不过。

以非阻塞方式完成后退出线程的正确方法是什么?

【问题讨论】:

您应该添加稍后运行的代码:self.thisSound.wait(); self.thisSound = None; 另外,您的类中不要有 __del__(self): 方法。 使用QSound。它非常简单,而且不需要多线程。 @ekhumoro 我可能会听从你的建议。我目前使用的pydub 似乎也有中途终止声音的问题,即使在我尝试删除线程后它们也会继续。尽管如此,它还是很欣赏了解线程的一点 @ekhumoro,抱歉回复晚了,我终于要试试了。 QSound 实际上似乎比多线程执行得更差,因为它在调用 QSound.play() 和实际结果之间至少有 1 秒的延迟,这很烦人。不知道如何解决它,关于这个主题的最新答案来自 2011 年。现在要坚持使用线程 @AleksejsFomins 对我来说(在 arch linux 上)声音会立即播放,没有明显的延迟。文档说创建QSound 对象并调用play() 插槽在某些系统上可能比使用静态函数更直接。然而,对我来说,它们都可以立即播放(即使是 40Mb 的 wav 文件)。我想在对大文件使用静态函数时,速度较慢的设备(例如网络驱动器或旧硬盘)可能会引入轻微的延迟。使用QSound 对象会将文件预加载到内存中,因此它的性能应该更高。 【参考方案1】:

为什么要删除它?我没有看到任何“del”调用,并且您将其分配给实例,因此 GC 也没有,因为仍然存在引用。

如果你想删除它,你必须这样做:

class MainClass(...):
    ...

    def playsound(self, soundKey):
        self.thisSoundThread = playSoundThread(self.sounds[soundKey])
        self.thisSoundThread.finished.connect(self.threadfinished)
        self.thisSoundThread.start()

    def threadfinished(self)
        del self.thisSoundThread
        # or set it to None

【讨论】:

正如我所说,我确实尝试了del self.thisSoundThread,但它被阻止了。我不知道finished 事件,它的话。所以谢谢:)

以上是关于完成后如何自动退出PyQT QThread?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用pytest正确退出队列和Qthread进行测试?

PyQt:如何终止可重用的 QThread

微信小程序自动退出

如何在自动完成字段角度启用退格

在 PyQt5 中取消 QThread

如何显示 PySide/PyQt UI 并自动运行其中一种方法?