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
- 您正在尝试执行 Qt 的内置操作:QThreadPool。
我建议您阅读文档并改用它。
如果你真的想使用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()
我在 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
- 您正在尝试执行 Qt 的内置操作:QThreadPool。
我建议您阅读文档并改用它。
如果你真的想使用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()