简体   繁体   English

如何从 GUI 应用程序正确终止 QThread?

[英]How to properly terminate a QThread from a GUI application?

I tried using self.terminate() in the QThread class, and also self.thread.terminate() in the GUI class. I also tried putting self.wait() in both cases.我尝试在 QThread class 中使用self.terminate() self.thread.terminate()在 GUI class 中使用 self.thread.terminate()。我还尝试在这两种情况下self.wait() However, there are two scenarios that happen:但是,会发生两种情况:

1) The thread does not terminate at all, and the GUI freezes waiting for the thread to finish. 1) 线程根本没有终止,GUI 冻结等待线程完成。 Once the thread finished, the GUI unfreezes and everything is back to normal.线程完成后,GUI 解冻,一切恢复正常。

2) The thread indeed does terminate, but at the same time it freezes the entire application. 2)线程确实终止了,但同时冻结了整个应用程序。

I also tried using self.thread.exit() .我也尝试使用self.thread.exit() No joy.没有快乐。

To further clarify, I am trying to implement a user-abort button in GUI which would terminate the executing of the thread at any point in time.为了进一步澄清,我正在尝试在 GUI 中实现一个用户中止按钮,该按钮将在任何时间点终止线程的执行。

Thanks in advance.提前致谢。

EDIT:编辑:

Here is the run() method:这是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

And here is the GUI class' method for aborting the thread:这是用于中止线程的 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

From the Qt documentation for QThread::terminate:从 QThread::terminate 的 Qt 文档中:

Warning : This function is dangerous and its use is discouraged.警告:此功能很危险,不鼓励使用。 The thread can be terminated at any point in its code path.线程可以在其代码路径中的任何一点终止。 Threads can be terminated while modifying data.修改数据时可以终止线程。 There is no chance for the thread to clean up after itself, unlock any held mutexes, etc. In short, use this function only if absolutely necessary.线程没有机会自行清理,解锁任何持有的互斥锁等。简而言之,只有在绝对必要时才使用此功能。

It's probably a much better idea to re-think your threading strategy such that you can eg use QThread::quit() to signal the thread to quit cleanly, rather than trying to get the thread to terminate this way.重新考虑您的线程策略可能是一个更好的主意,例如,您可以使用 QThread::quit() 来通知线程干净地退出,而不是试图让线程以这种方式终止。 Actually calling thread.exit() from within the thread should do that depending on how you have implemented run().实际上,从线程内部调用 thread.exit() 应该这样做,具体取决于您实现 run() 的方式。 If you'd like to share the code for your thread run method that might hint as to why it doesn't work.如果你想分享你的线程运行方法的代码,它可能会暗示它为什么不起作用。

This is what I did:这就是我所做的:

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")

I had a similar problem and solved it with use of pyqtSignals and pyqtSlots .我有一个类似的问题并使用pyqtSignalspyqtSlots解决了它。 You could create a pyqtSignal in your MainWindow-class and use the aboutToQuit -function to your QApplication instance.您可以在 MainWindow 类中创建一个pyqtSignal并将aboutToQuit -函数用于您的QApplication实例。 Then you connect this aboutToQuit -function with another which emit a signal to the slot in your separate thread.然后将这个aboutToQuit函数与另一个函数连接起来,后者会向单独线程中的插槽发出信号。 Then you can define a stop() function in this Thread which runs if the signal is emitted.然后,您可以在此线程中定义一个stop() function,如果发出信号,它就会运行。 In this case the thread would not terminate during its work.在这种情况下,线程不会在其工作期间终止。

MainWindow:主窗口:

class mainSignals(QObject):
    isClosed = pyqtSignal()

class mainwindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(mainwindow, self).__init__()
        self.mainSignal = mainSignals()
        ...
        ...

if __name__ = "__main__":
    # This function runs if the application is closed. 
    # (app.aboutToQuit.connect(windowClose))
    def windowClose():
        window.mainSignal.isClosed.emit() # Emit the signal to the slot in (sepThread)


    app = QApplication(sys.argv)
    app.aboutToQuit.connect(windowClose)
    window = mainwindow()
    window.show()
    sys.exit(app.exec())

sepThread :分离线程

class sepThread(QRunnable):
    def __init__(self, parent):
        super(sepThread,self).__init__()
        self._parent = parent
        self.mainOpen = True
        self._parent.mainSignal.isClosed.connect(self.stopThread)
        # If the signal was emitted by the Mainapplication 
        # the stopThread function runs and set the mainOpen-attribute to False

    def stopThread(self):
        self.mainOpen = False
    
        
    def run(self):
        while self.mainOpen == True:
            # Do something in a loop while mainOpen-attribute is True
            ...
            ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM