PySide:线程在 运行 时被破坏

PySide: Threads destroyed whie still running

我在 python 中遇到 QThreads 问题。 当我按下按钮 运行.

时,我想启动我的多 QThread

但是编译器输出如下错误: "QThread: Destroyed while thread is still running"

我不知道我的代码有什么问题。 任何帮助,将不胜感激。 这是我的代码:

# -*- coding: utf-8 -*-
from PySide import QtCore, QtGui
from Ui_MainWindow import Ui_MainWindow
from queue import Queue
import sys, re, random
import time, random, re, urllib.request
from urllib.parse import urljoin

class Worker(QtCore.QThread):
    def __init__(self,threadID, name, q, delay):
        QtCore.QThread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.q = q
        self.delay = delay
        self._running = False

    def run(self):
        self._running = True
        print ("start - %s" %self.name)
        while self._running:
            req = self.request(self.name,  self.q, self.delay)

    def stop(self, wait=False):
        print (self.name)
        self._running = False


    def request(self, threadName, q1, delay):
        while not self.q.empty():
            time.sleep(delay)
            q = q1.get()
            print ("%s: %s %s %s" % (threadName, time.ctime(time.time()), q, delay))
        if self.q.empty():
            print ("queue empty")
            self.stop()

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.backend = Queue()
        self.connect(self.ui.actionStart, QtCore.SIGNAL('triggered()'),self.start)

    def start(self):
        try :
            f1 = open('./payload/backend.log')
        except FileNotFoundError as e:
            return

        threadList = ["Thread-1", "Thread-2", "Thread-3", "Thread-4", "Thread-5"]
        self.url = "http://test.com"
        self.threads = []
        threadID = 1

        for payload in f1.read().splitlines() :
            full_url = urljoin(self.url, payload)
            self.backend_dir.put(full_url)


        for tName in threadList:
            ran_int = random.randint(1, 2)
            downloader = Worker(threadID, tName, self.backend, ran_int)
            downloader.start()
            self.threads.append(downloader)


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_()) 

日志

QThread: Destroyed while thread is still running
QThread: Destroyed while thread is still running
QThread: Destroyed while thread is still running
QThread: Destroyed while thread is still running
  1. 您正在尝试执行 Qt 的内置操作:QThreadPool

我建议您阅读文档并改用它。

  1. 如果你真的想使用QThread: 你不应该继承 QThread。相反,你应该继承基本的 QObject 来创建你的工人并使用 moveToThread 方法:

    class WorkerSignals(QObject):
        finished = pyqtSignal()
    
    class Worker(QObject):
        def __init__():
            self.signal = WorkerSignals()
    
            def run(self):
            # Your stuff
            print('running')
            self.signal.finished.emit()
    

然后在其他地方:

    thread = QThread()
    worker = Worker(...)
    worker.moveToThread(thread)
    thread.started.connect(worker.run)
    worker.finished.connect(thread.quit)
    worker.finished.connect(worker.deleteLater)
    thread.finished(thread.deleteLater)
    thread.start()

解决方案是这个在 C++ 中的粗略翻译: https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

希望对您有所帮助!

我认为您需要在 downloader.start() 之前调用 self.threads.append(downloader) ,这样线程就不会超出范围并被垃圾回收。

问题是由您使用队列的方式引起的。

所有线程开始并正常开始它们的任务,直到队列变空。那时,第一个完成的线程终止,但其他四个线程仍在等待从队列中返回的项目,该项目永远不会到来。

这是因为你使用了get with no arguments, which will block indefinitely until an item becomes available. Instead, you should use get_nowait,而且在request()末尾也无条件调用了stop()

from queue import Queue, Empty
...

class Worker(QtCore.QThread):
     ...

    def request(self, threadName, q1, delay):
        while not q1.empty():
            time.sleep(delay)
            try:
                q = q1.get_nowait()
            except Empty:
                break
            else:
                print ("%s: %s %s %s" % (threadName, time.ctime(time.time()), q, delay))
        print ("queue empty")
        self.stop()