如何停止线程的执行

在下面的代码中,我有类 The Thread,它继承自线程以在不同的线程中执行任务,在这种情况下,任务是在 QLabel 中显示 .gif 图像,同时执行另一个任务。


在这种情况下,当发出执行 Finish() 函数的信号时,tabWidget() 小部件从 index 变为 1


但是当我们返回索引 0 时,我们可以看到 .gif 仍在 QLabel 中运行。


所以我想知道如何停止该线程的执行,我试过了


TheThread.kill()

TheThread.stop()

但它不起作用,这是带有 .ui 文件和 image.gif 的完整代码


from PyQt5.QtWidgets import QMainWindow,QApplication,QTabWidget,QPushButton,QLabel

from PyQt5 import QtCore,QtGui

from PyQt5 import uic

import threading

import time


class TheThread(threading.Thread):

    def __init__(self,obj,fun):

        threading.Thread.__init__(self)


        self.obj = obj

        self.fun = fun


    def run(self):

        self.fun()

class Main(QMainWindow):

    signal = QtCore.pyqtSignal(object)

    def __init__(self):

        QMainWindow.__init__(self)

        uic.loadUi("Test.ui",self)


        self.Iniciar.clicked.connect(lambda:self.ShowImage())


        self.signal.connect(self.Finish)

        self._thread = TheThread(self,self.Fun1)


    def ShowImage(self):

        _movie = QtGui.QMovie("Loader.gif")

        self.Animacion.setMovie(_movie)

        self.Animacion.setScaledContents(True)

        _movie.start()


        self._thread.start()


    def Fun1(self):

        time.sleep(3)

        self.signal.emit(0)


    def Finish(self,signal):

        if signal == 0:

            time.sleep(1)


            self.tabWidget.setCurrentIndex(1)

            # TheThread.kill()

            TheThread.stop()



app = QApplication([])

m = Main()

m.show()

app.exec_()


眼眸繁星
浏览 225回答 2
2回答

小怪兽爱吃肉

您的描述与您的代码不符,也不符合正确的逻辑。作为 GUI 一部分的 gif 必须在主线程(GUI 线程)中执行,而繁重的任务则在辅助线程中执行。不要在主线程中使用 time.sleep()。它完成执行繁重的任务并不意味着它完成了 gif 的执行,您必须停止它。考虑到上述情况,一种更简单的方法是创建一个存在于另一个线程中的 QObject 并在那里执行任务,这允许您添加启动和完成信号。import osimport timefrom functools import partialfrom PyQt5 import QtCore, QtGui, QtWidgets, uiccurrent_dir = os.path.dirname(os.path.realpath(__file__))def callback():    # emulate task    time.sleep(3.0)class Worker(QtCore.QObject):    started = QtCore.pyqtSignal()    finished = QtCore.pyqtSignal()    @QtCore.pyqtSlot(object)    def task(self, fun):        self.started.emit()        fun()        self.finished.emit()class Main(QtWidgets.QMainWindow):    def __init__(self, parent=None):        super(Main, self).__init__(parent)        filename = os.path.join(current_dir, "Test.ui")        uic.loadUi(filename, self)        self.Animacion.setScaledContents(True)        thread = QtCore.QThread(self)        thread.start()        self._worker = Worker()        self._worker.moveToThread(thread)        self._worker.started.connect(self.show_image)        self._worker.finished.connect(self.on_finished)        wrapper = partial(self._worker.task, callback)        self.Iniciar.clicked.connect(wrapper)    @QtCore.pyqtSlot()    def show_image(self):        _movie = QtGui.QMovie("Loader.gif")        self.Animacion.setMovie(_movie)        self.Animacion.movie().start()    @QtCore.pyqtSlot()    def on_finished(self):        self.tabWidget.setCurrentIndex(1)        self.Animacion.movie().stop()def main():    import sys    app = QtWidgets.QApplication(sys.argv)    w = Main()    w.show()    sys.exit(app.exec_())if __name__ == "__main__":    main()

慕标5832272

您使用了错误的线程,更好的方法是使用 Qt GUI 线程。stop()但是,除了使用orkill()方法(顺便说一句,它们不应该被设置为self._thread您定义的变量而不是TheThread类吗?)之外,我发现演示在 Python 中杀死线程的多种方法很好。这些技术本质上是骇人听闻的,但它们确实有效。首先,您可以抛出异常,因为异常总是会阻止代码执行。此示例使用该ctypes库:import ctypesdef get_id(self):     # returns id of the respective thread     if hasattr(self, '_thread_id'):         return self._thread_id     for id, thread in threading._active.items():         if thread is self:             return iddef raise_exception(self):     thread_id = self.get_id()     res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,           ctypes.py_object(SystemExit))     if res > 1:         ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)         print('Exception raise failure') self._thread.raise_exception();您还可以使用布尔标志变量,当设置为 true 时,执行一个break语句,结束程序。您可以在run()函数中定义线程,然后该join()方法基本上停止线程:def run():    while True:       global stop_threads        if stop_threads:           breakself._thread = threading.Thread(target = run)  self_thread.start() stop_threads = Trueself_thread.join()您还可以使用多处理模块,而不是使用线程,您可以使用进程,这非常相似,唯一的区别是线程在相同的内存空间中运行,而进程具有单独的内存。该terminate()方法杀死进程:import multiprocessing import time def func(number):    for i in range(1, 10):        time.sleep(0.01)        print('Processing ' + str(number) + ': prints ' + str(number*i)) all_processes = [] for i in range(0, 3):    process = multiprocessing.Process(target=func, args=(i,))    process.start()    all_processes.append(process) # Kill all processes after 0.03s  time.sleep(0.03) for process in all_processes:    process.terminate()最后,您可以通过将线程设置为守护进程来终止该线程。默认情况下,线程不会在程序结束时结束,所以守护线程是那些在主程序退出时被杀死的线程:def func():    while True:       time.sleep(0.5)       print('Thread alive, but it will die on program termination') self._thread = threading.Thread(target=func) self._thread.daemon = Trueself._thread.start() time.sleep(2)sys.exit()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python