pyqt5 QThread: Destroyed while thread is still

  • A+
所属分类:编程语言

pyqt5的主界面中需要填充网络数据,但是获取网络数据是需要耗时的,如果直接放在主界面中获取会导致界面卡死,必须要通过QThread多线程来获取,但是往往又会碰到程序闪崩的情况,经过具体排查会发现提示信息 QThread: Destroyed while thread is still ,意思是QThread的子线程还在运行但是线程就被销毁了,因此才会导致程序闪崩。这个错误信息需要通过在cmd命令行中运行程序才会具体看到提示信息。

解决线程问题有几种方式,这里推荐如下:在子线程前面加上self, 从而让send_message_worker 变为实例变量,随着程序的存在而存在,不会因为send_message_process函数的结束而导致子线程还在运行就直接被销毁。这里有一点需要注意,在子线程中加入了完成的信号,当线程完成后调用deleteLater,这样避免子线程一直存在占用内存。

  1. def send_message_process(self):
  2.     self.send_message_worker = SendMessageThread()
  3.     self.send_message_worker.finished.connect(self.send_message_worker.deleteLater)
  4.     self.send_message_worker.start()

虽然通过让函数中的临时变量转化为整个程序的实例变量,从而避免了子线程在运行中就被销毁的问题,但是这种方式又会引起新问题而且比较隐蔽。当运行函数,子程序结束后,再次运行函数没有问题。但是当函数运行后子线程还在进行中,若此时再次运行就会重新初始化实例变量,导致之前运行的子线程又被中途销毁的问题出现,程序闪崩。因此,好的解决方式是直接初始化一个实例列表变量self.task_list,每次初始化子线程后将临时变量加入到实例变量中这样也能实现变量随着程序长时间存在。

在子线程结束后,发送一个完成的信号,获取信号发送对象sender,然后判断对象是否在self.task_list中,如果在的话就移除对象从而达到子线程完成后主动销毁线程解除内存占用。

  1. def send_message_process(self)
  2.     send_message_worker = SendMessageThread()
  3.     self.task_list.append(send_message_worker)
  4.     send_message_worker.finished.connect(self._remove_thread)
  5.     send_message_worker.start()
  6. def _remove_thread(self):
  7.     sender = self.sender()
  8.     # print('前',self.task_list)
  9.     if sender in self.task_list:
  10.         try:
  11.             self.task_list.remove(sender)
  12.         except Exception as e:
  13.             print(e)
  14.     # print('后',self.task_list)

 

weinxin
我的微信公众号
爱真理,得永生!          爱在灵灵久博客,网罗天下,福利大家!

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: