PySide:线程在仍在运行时被破坏

时间:2015-01-20 08:38:15

标签: python multithreading queue pyside

我在python中遇到QThreads问题。 当我按下Run按钮时,我想启动我的多QThread。

但编译器输出以下错误: " QThread:在线程仍在运行时被销毁"

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

# -*- 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

3 个答案:

答案 0 :(得分:1)

  1. 你正在尝试做一些内置的Qt:QThreadPool
  2. 我建议你阅读文档并使用它。

    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()
      
    2. 然后在其他地方:

          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/

      希望这有帮助!

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

所有线程都正常启动并开始其任务,直到队列变空。此时,第一个完成的线程终止,但剩下的四个线程等待从队列返回一个项目,这从未到来。

这是因为你使用没有参数的get,它会无限期地阻塞,直到一个项目可用。相反,您应该使用get_nowait,并在stop()结束时无条件地致电request()

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