如何停止线程的执行 [英] How to stop the execution of a thread

查看:47
本文介绍了如何停止线程的执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In the following code I have the class The Thread, which inherits from threading to execute a task in a different thread, in this case the task is to show a.gif image in a QLabel, while another task is executed.

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

In this case, when emitting the signal that executes the Finish() function, the tabWidget() widget changes from index to 1

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

But when we return to index 0 we can see that the .gif is still running in the QLabel.

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

So I want to know how to stop the execution of that thread, I tried

TheThread.kill()
TheThread.stop()

但是没有用,这是包含 .ui 文件和 image.gif 的完整代码

But it didn't work, this is the complete code with the .ui file and the 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_()

文件.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QTabWidget" name="tabWidget">
    <property name="geometry">
     <rect>
      <x>30</x>
      <y>0</y>
      <width>691</width>
      <height>441</height>
     </rect>
    </property>
    <widget class="QWidget" name="tab">
     <attribute name="title">
      <string>Tab 1</string>
     </attribute>
     <widget class="QLabel" name="Animacion">
      <property name="geometry">
       <rect>
        <x>220</x>
        <y>40</y>
        <width>231</width>
        <height>171</height>
       </rect>
      </property>
      <property name="text">
       <string>TextLabel</string>
      </property>
     </widget>
     <widget class="QLabel" name="Estatus">
      <property name="geometry">
       <rect>
        <x>220</x>
        <y>270</y>
        <width>271</width>
        <height>16</height>
       </rect>
      </property>
      <property name="text">
       <string>TextLabel</string>
      </property>
     </widget>
    </widget>
    <widget class="QWidget" name="tab_2">
     <attribute name="title">
      <string>Tab 2</string>
     </attribute>
    </widget>
   </widget>
   <widget class="QPushButton" name="Iniciar">
    <property name="geometry">
     <rect>
      <x>30</x>
      <y>460</y>
      <width>75</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>PushButton</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

Image.gif

推荐答案

您的描述与您的代码不符,也不符合正确的逻辑.

Your description does not match your code, nor with the correct logic.

  • 作为 GUI 一部分的 gif 必须在主线程(GUI 线程)中执行,而繁重的任务在辅助线程中执行.

  • The gif that is part of the GUI must be executed in the main thread (GUI thread) and the heavy task in the secondary thread.

不要在主线程中使用time.sleep().

Do not use time.sleep () in the main thread.

它完成了繁重的任务并不意味着它已经完成了 gif 的执行,你必须停止它.

That it finishes executing the heavy task does not imply that it is finished executing the gif, you have to stop it.

考虑到上述情况,一个更简单的方法是创建一个位于另一个线程中的 QObject 并在那里执行任务,这样您就可以添加开始和完成的信号.

Considering the above, a simpler approach is to create a QObject that lives in another thread and execute the task there, that allows you to add the started and finished signals.

import os
import time
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets, uic


current_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()

这篇关于如何停止线程的执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆