Python如何安全地挂起、恢复、终止Qthread线程

Python如何安全地挂起、恢复、终止Qthread线程

我是一个Python初学者,最近在用PyQt5做Gui的时候遇到一个烧脑的问题,如何安全的实现线程的暂停、终止。如果粗暴的kill掉线程,比如说线程正在requests一个数据,这样总感觉不太好,于是查阅了1晚上的各种资料(没有老师教,没地请教,只能自己动手~呜呜呜呜)。

为啥threading仅有start而没有end?

线程一般用在网络连接、释放系统资源、dump流文件,这些都跟IO相关了,你突然关闭线程那这些
没有合理地关闭怎么办?是不是就是给自己造bug呢?

经过各种资料的查询,有使用TerminateThread强行终止线程的,有使用thread.join阻塞线程的(原来我还不是特别明白),经过思考我想到了一直不借助任何其他库,用基本函数就可以实现的线程挂起、终止的办法。

简单来说,就是定义个线程stop状态的全局变量,每次线程循环的时候就检查一下这个变量是不是提示自己该停止或者暂停或者恢复了,而且不强行终止线程,还可以重新开启。废话不多说,直接上代码:

# An highlighted block
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QProgressBar, QPushButton
import time

class Worker(QThread):
    valueChanged = pyqtSignal(int)  # 值变化信号
    status = pyqtSignal(int)
    def run(self):
        print('thread id', int(QThread.currentThreadId()))
        # 循环发送信号
        break2 = False  #break标志量
        for i in range(1, 101):
            if stop_status == 1:   #停止信号1
                self.valueChanged.emit(0)   
                #这个地方如果有进程锁,需要在这里解锁,当然也可以直接用break,但是break会执行后面的语句
                print('程序结束')
                return
            elif stop_status == 2:  #暂停信号2
                while 1:
                    if stop_status == 2:
                        time.sleep(0.1)  #必须有time.sleep 可以有效降低cpu消耗
                        continue
                    elif stop_status == 1:    #停止信号1
                        break2 = True   #break标志量,外层继续执行break
                        break   #跳出无限循环
                    else:  #恢复信号0 
                        break
            else:
                pass             
            if(break2):  #跳出外层for循环
                break
            print('value', i)
            self.valueChanged.emit(i)
            time.sleep(0.5)
        self.status.emit(0)
        
class Window(QWidget):

    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)
        # 垂直布局
        layout = QVBoxLayout(self)
        self.progressBar = QProgressBar(self)
        self.progressBar.setRange(0, 100)
        layout.addWidget(self.progressBar)
        self.startButton = QPushButton('开启线程', self, clicked=self.onStart)
        layout.addWidget(self.startButton)
        self.suspendButton = QPushButton('挂起线程', self, clicked=self.onSuspendThread, enabled=False)
        layout.addWidget(self.suspendButton)
        self.resumeButton = QPushButton('恢复线程', self, clicked=self.onResumeThread, enabled=False)
        layout.addWidget(self.resumeButton)
        self.stopButton = QPushButton('终止线程', self, clicked=self.onStopThread, enabled=False)
        layout.addWidget(self.stopButton)

        # 当前线程id
        print('main id', int(QThread.currentThreadId()))

        # 子线程
        self._thread = Worker(self)
        #self._thread.finished.connect(self._thread.deleteLater)
        self._thread.valueChanged.connect(self.progressBar.setValue)

    def onStart(self):
        global stop_status
        stop_status = 0 
        print('main id', int(QThread.currentThreadId()))
        self._thread.start()  # 启动线程
        self.startButton.setEnabled(False)
        self.suspendButton.setEnabled(True)
        self.stopButton.setEnabled(True)

    def onSuspendThread(self):
        global stop_status
        stop_status = 2
        print('挂起线程')
        self.suspendButton.setEnabled(False)
        self.resumeButton.setEnabled(True)

    def onResumeThread(self):
        global stop_status
        stop_status = 0
        print('恢复线程')
        self.suspendButton.setEnabled(True)
        self.resumeButton.setEnabled(False)

    def onStopThread(self):
        global stop_status
        stop_status = 1
        self.startButton.setEnabled(True)
        self.resumeButton.setEnabled(False)
        self.progressBar.setRange(0, 100)
        print('终止线程')
        self.stopButton.setEnabled(False)

if __name__ == '__main__':
    import sys
    import os
    print('pid', os.getpid())
    from PyQt5.QtWidgets import QApplication
    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值