我正在PyQt5中制作一个应用程序,该应用程序可以运行各种长时间运行的任务,例如抓取网页。为了避免使GUI崩溃,我一直在使用QThreads和QObjects
目前,我有一个继承QObject的类,其中包含用于抓取网页的方法。我将该对象移到QThread上,将完成信号与退出线程的方法连接,然后启动线程。
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import threading
from concurrent.futures import ThreadPoolExecutor
import requests
class Main(QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.init_ui()
self.test_obj = None
self.thread = QThread(self)
def init_ui(self):
widget = QWidget()
layout = QHBoxLayout()
widget.setLayout(layout)
thread_button = QPushButton("Start Thread")
check_button = QPushButton("Check Thread")
layout.addWidget(thread_button)
layout.addWidget(check_button)
thread_button.clicked.connect(self.work)
check_button.clicked.connect(self.check)
self.setCentralWidget(widget)
self.show()
def work(self):
self.test_obj = TestObject()
self.test_obj.moveToThread(self.thread)
self.test_obj.finished.connect(self.finished)
self.thread.started.connect(self.test_obj.test)
self.thread.start()
def check(self):
for t in threading.enumerate():
print(t.name)
@pyqtSlot()
def finished(self):
self.thread.quit()
self.thread.wait()
print("Finished")
class TestObject(QObject):
finished = pyqtSignal()
def __init__(self):
super(TestObject, self).__init__()
def test(self):
with ThreadPoolExecutor() as executor:
executor.submit(self.get_url)
self.finished.emit()
def get_url(self):
res = requests.get("http://www.google.com/")
print(res)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Main()
sys.exit(app.exec_())
一切正常,我得到一个:
“响应[200]” “完成”
在控制台中打印。但是,当我检查正在运行的线程时,它表明dummy-1线程仍在运行。每次运行时,它都会创建一个附加的虚拟线程。最终,我无法再创建更多线程,并且我的应用程序崩溃了。
是否可以在像这样的QThread上使用ThreadPoolExecutor?如果是这样,有没有一种正确的方法来确保我在完成任务后仍不运行这些虚拟线程?