Pyqt5如何停止多线程

Pyqt5如何停止多线程,第1张

以下用一个简单例子来表现如何用signal/slot信号槽来退出线程

若有一个按钮,点击开始线程,再次点击退出线程,线程的工作为打印a(1-20)然后b(1-20),线程代码如下:

[python] view plain copy

class UpdateThread(QThread):

def __init__(self, parent=None):

super(UpdateThread, self).__init__(parent)

self.flag = 1# 用来判断循环是否继续的标志,通过改变该标志来使得线程中run函数退出

def run(self):

table = ['a', 'b', 'c', 'd ', 'e', 'f', 'g']

for i in range(6):

if self.flag == 1:

print table[i]

for m in range(20):

print m

time.sleep(0.5)

else:

break

print 'close'# 输出标明线程run函数已经退出

def stop(self):

print 'setting flag false'

self.flag = 0

print self.flag

一开始因为python的threading没有线程退出的api,了解到QThread有实现线程的阻塞,退出,强制退出等api,于是就将线程继承了QThread,但是在gui界面的按钮逻辑中写上mythread.wait()或者是quit()还是terminate()都无法对线程产生影响(可能是当时没有使用信号槽机制,所以不起作用),然后自己来写一个stop函数用来修改线程中的一个标志,使得run函数中的循环停止,然后就如上代码所示,在按钮逻辑中如下所写(错误示范):

[python] view plain copy

def update_db():# error

self.new_thread1 = UpdateDbThread()

if self.update_tag == 0:

self.update_tag = 1

self.new_thread1.start()

else:

self.update_tag = 0

self.new_thread1.stop()

运行之后发现stop函数虽然改变了self.flag的值,但是循环中判断语句中flag的值依然为1,循环并没有停止,然后就去查阅资料,以及上stackoverflow寻找答案,最终知道了线程需要通过信号槽机制来响应,所以便去查阅qt的signal/slot的相关信息,修改按钮代码如下:

[python] view plain copy

class mywidget(Qwidget):

sin = pyqtSignal()# 提前申明

def __init__(self):

...

self.new_thread1 = UpdateDbThread()

self.sin.connect(self.new_thread1.stop)

def update_db():

if self.update_tag == 0:

self.update_tag = 1

self.new_thread1.start()

else:

self.update_tag = 0

self.sin.emit()

[python] view plain copy

</pre><p></p><pre>

pyqtSignal信号的定义不可以写在update_db方法中,也不可以写在init()初始化方法中,原因如下(来自stackoverflow):

所以我们就在init方法之前定义好信号sin,然后连接上线程的stop方法。点击按钮发送信号,就好改变线程的标志,然后从循环中退出,运行结果如下:

为了便于贴图,我将循环输出改为了10:

线程正常退出,目标达成。可以根据自己的需要重写run方法。

还有需要注意的是,不可以在方法中写上 mythread = update_db() ,这样在运行时会报错,destroyed while thread is running,因为在方法中mythread是一个局部变量,当方法结束时,python的垃圾回收机制就会自动销毁,然后就会出现以上错误,所以必须在mythread的前面加上self,使得线程成为全局变量。

线程只执行一次……让我来猜一猜。

你可能会认为创建一个线程去执行某个动作就完事了?

一段代码不管是在主线程里还是在新建的线程里,它都是按代码本身的规则那么执行的,该循环就循环,该结束就结束。

所以,我们建立一个线程去执行某个动作,主要就是让这个动作的执行不影响主程的执行,不要因为它导致主程序的某环节等待这个动作的结果。

举例来说,一个定时3秒去读一下某个文件,总不能做个循环,读一下文件,然后sleep3秒吧,那除了这个,什么也干不了,基本都是在【等待3秒】这里耗着了。解决办法就是做个线程去完成【读某个文件】,然后这个事完了之后、前再建一个同样的线程让它三秒后执行。

看下图:

这个sort_loop就是这样干的:

【红框2】就是主要的工作内容(对self.data进行收缩)

如果简简单单的就这,那它就执行一次就完事了,哪怕你把sort_loop放到新线程里,也是一样。

要在sort_loop里再新建一个线程,新线程还是执行sort_loop,于是就是这样的:

A把桌子擦了擦,把抹布塞给了B;

B把桌子擦了擦,把抹布塞给了C

C把桌子擦了擦,把抹布塞给了D...

这才构成一个线程循环。

系统安装的有问题。直接换个验证过的系统盘重装系统就行了,这样就可以全程自动、顺利解决系统无法安装的问题了。用u盘或者硬盘这些都是可以的,且安装速度非常快。但关键是:要有兼容性好的(兼容ide、achi、Raid模式的安装)并能自动永久激活的、能够自动安装机器硬件驱动序的系统盘,这就可以全程自动、顺利重装系统了。方法如下:

1、U盘安装:用ultraiso软件,打开下载好的系统安装盘文件(ISO文件),执行“写入映像文件”把U盘插到电脑上,点击“确定”,等待程序执行完毕后,这样就做好了启动及安装系统用的u盘,用这个做好的系统u盘引导启动机器后,即可顺利重装系统了;

2、硬盘安装:前提是,需要有一个可以正常运行的Windows系统,提取下载的ISO文件中的“*.GHO”和“安装系统.EXE”到电脑的非系统分区,然后运行“安装系统.EXE”,直接回车确认还原 *** 作,再次确认执行自动安装 *** 作。(执行前注意备份C盘重要资料!)。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/12165277.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-21
下一篇2023-05-21

发表评论

登录后才能评论

评论列表(0条)

    保存