【问题标题】:How to properly terminate a QThread from a GUI application?如何从 GUI 应用程序中正确终止 QThread?
【发布时间】:2011-12-17 04:50:32
【问题描述】:

我尝试在 QThread 类中使用 self.terminate(),并在 GUI 类中使用 self.thread.terminate()。我还尝试在这两种情况下都输入self.wait()。但是,有两种情况会发生:

1) 线程根本没有终止,GUI 冻结等待线程完成。线程完成后,GUI 解冻,一切恢复正常。

2) 线程确实终止了,但同时它冻结了整个应用程序。

我也尝试过使用self.thread.exit()。不开心。

为了进一步澄清,我正在尝试在 GUI 中实现一个用户中止按钮,该按钮将在任何时间点终止线程的执行。

提前致谢。

编辑:

这里是run() 方法:

def run(self):
    if self.create:
        print "calling create f"
        self.emit(SIGNAL("disableCreate(bool)"))
        self.create(self.password, self.email)
        self.stop()            
        self.emit(SIGNAL("finished(bool)"), self.completed)

def stop(self):
     #Tried the following, one by one (and all together too, I was desperate):
     self.terminate()
     self.quit()
     self.exit()
     self.stopped = True
     self.terminated = True
     #Neither works

下面是 GUI 类中止线程的方法:

def on_abort_clicked(self):
     self.thread = threadmodule.Thread()
     #Tried the following, also one by one and altogether:
     self.thread.exit()
     self.thread.wait()
     self.thread.quit()
     self.thread.terminate()
     #Again, none work

【问题讨论】:

  • 注意:self.terminate === (self.terminated = true),仅此而已。 99% 的实现。
  • 谢谢,但这并不能真正帮助解决问题。
  • 只有一种方法可以安全地终止线程——让它完成所有的任务。要执行它,您必须在执行硬任务之前检查 thread.terminated。
  • 嗯,这当然不是我要找的。​​span>

标签: python multithreading qt pyqt


【解决方案1】:

来自 QThread::terminate 的 Qt 文档:

警告:此功能很危险,不鼓励使用。这 线程可以在其代码路径中的任何位置终止。线程可以 修改数据时终止。线程没有机会 自行清理,解锁任何持有的互斥锁等。简而言之,使用 仅在绝对必要时才使用此功能。

重新考虑你的线程策略可能是一个更好的主意,这样你就可以例如使用 QThread::quit() 来通知线程干净地退出,而不是试图让线程以这种方式终止。实际上,从线程内调用 thread.exit() 应该取决于您实现 run() 的方式。如果你想分享你的线程运行方法的代码,这可能会暗示它为什么不起作用。

【讨论】:

  • 嗯。我假设self.create() 方法是线程中耗时的方法?通常你会在那里做类似while not self.terminated() { do slow operation parts.. }的事情。不幸的是,我不太了解 Python,但看起来有一个线程教程 here 可能会有所帮助
  • 我也试过了。它碰巧有点工作(GUI 不会冻结,但线程也不会终止)。然而,最奇怪的事情发生了。我删除了线程中的所有def stop(self)代码和GUI中的def on_abort_clicked(self)代码,并重写了它。我只是将self.terminate() 放在线程的stop() 函数中,并在GUI 类中做了self.thread.stop()。它就像一个魅力。 AFAIK,这是我尝试的第一件事,但以前没有用。我可能错过了什么。
【解决方案2】:

这就是我所做的:

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    stop_flag = 1
    ...

#=========500 ms class ===================
class Timer500msThread(QThread):
    signal_500ms = pyqtSignal(str) 
    ....
    def timer500msProcess(self):
        if MainWindow.stop_flag == 0 :
            self.timer_500ms.stop()
#==========
#=========Main Window ===================
        
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
MainWindow.stop_flag=0      #this sets the flag to 0 and when the next 500ms triggers the 
                               #the thread ends
print("Program Ending")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-21
    • 1970-01-01
    • 2019-10-05
    • 2012-04-30
    • 2010-12-26
    • 1970-01-01
    • 2021-01-15
    相关资源
    最近更新 更多