因此,我目前有一个PYQT应用程序,它结合了python内置的线程和QT Qthread/worker系统来支持异步活动 生成线程/工作者的代码是process_batch,它包含在一个名为Scraper的类中,该类是一个QObject
def process_batch(self, batch):
for worker in batch:
self.host.threads.append(QThread())
th = self.host.threads[len(self.host.threads)-1]
worker.moveToThread(th)
th.started.connect(worker.process)
qApp.aboutToQuit.connect(th.quit)
worker.finished.connect(worker.deleteLater)
th.finished.connect(th.deleteLater)
for thread in self.host.threads:
thread.start()
self.activeThreads += 1
self.host。线程是一个列表变量helf由ScraperHost对象,该批处理变量是一个标准的python列表,有50个类:
class ScraperWorker(QObject):
complete = pyqtSignal(str)
start = pyqtSignal(str)
finished = pyqtSignal()
def __init__(self, url, task, _id):
QObject.__init__(self)
self.url = url
self.task = task
self.id = _id
self.start.connect(self.process)
def __str__(self):
return self.url
@pyqtSlot()
def process(self):
time.sleep(float(random.random() * random.randint(1,3)))
#self.complete.emit(str(self.id))
self.finished.emit()
时间。添加sleep是为了查看随机间隔线程的补全是否会修复这个问题,但它没有 最初,我遇到了一个问题:process_batch函数完成时,线程在完成之前被删除,所以我实现了self.host。防止它们被垃圾回收的线程。 线程包含如下:
class ScraperHost(threading.Thread):
def __init__(self, threadID, urls, task):
threading.Thread.__init__(self)
self.threadID = threadID
self.scraper = Scraper(urls, task, self)
self.threads = []
def run(self):
self.scraper.run()
刮板主机是创建在我的主窗口:
def selectFileList(self):
options = QFileDialog.Options()
fileName, _ = QFileDialog.getOpenFileName(self, "Select List","", "Excel File (*.xls *.xlsx)", options=options)
if fileName:
...
...
self.ScraperHost = ScraperHost(0, urls, "index")
self.ScraperHost.run()
目前,我可以运行零错误的函数/程序,但它只完成了线程的一半。它不会给我任何错误,信息,或任何指示,为什么他们没有完成。如果我将批处理大小增加到100,它就完成了50。如果我在VS代码中以调试模式运行它,我可以看到所有50个线程都被正确创建,并且都在主机中。线程变量。如果我在调试模式下一步一步地完成线程的创建,它们都将正确地完成,但是如果我只是正常地运行程序,只有一半将完成。每次结束的25个线程都是不同的,因为它们等待的时间是随机的。worker的self.finished.emit()只打印线程的ID,这是我看到多少完成的方式 旁注:通过更多,有时所有,但没有一致性的线程,当运行从空闲相对于VS代码
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import threading
import time
import random
scraperhost = None
class ScraperHost(threading.Thread):
def __init__(self, threadID, urls, task):
threading.Thread.__init__(self)
self.threadID = threadID
self.scraper = Scraper(urls, task, self)
self.threads = []
def run(self):
self.scraper.run()
class Scraper(QObject):
output = pyqtSignal(str)
complete = pyqtSignal()
def __init__(self, urls, task, host):
QObject.__init__(self)
self.urls = urls
self.batches = []
self.activeThreads = 0
self.task = task
self.host = host
def __del__(self):
self.wait()
def run(self):
batch_size = 50
batch_count = 1
for batch in range(0, batch_count):
self.batches.append([])
for i in range (0, batch_size):
try:
c_url = "www.website.com"
worker = ScraperWorker(c_url, self.task, i)
worker.complete.connect(self.worker_finished)
self.batches[batch].append(worker)
except IndexError:
break
if len(self.batches) == 0:
return
self.process_batch(self.batches.pop())
@pyqtSlot(str)
def worker_finished(self, ss):
self.activeThreads -= 1
print(self.activeThreads)
def process_batch(self, batch):
for worker in batch:
self.host.threads.append(QThread())
th = self.host.threads[len(self.host.threads)-1]
worker.moveToThread(th)
th.started.connect(worker.process)
qApp.aboutToQuit.connect(th.quit)
worker.finished.connect(worker.deleteLater)
th.finished.connect(th.deleteLater)
for thread in self.host.threads:
thread.start()
self.activeThreads += 1
class ScraperWorker(QObject):
complete = pyqtSignal(str)
start = pyqtSignal(str)
finished = pyqtSignal()
def __init__(self, url, task, _id):
QObject.__init__(self)
self.url = url
self.task = task
self.id = _id
self.start.connect(self.process)
def __str__(self):
return self.url
@pyqtSlot()
def process(self):
time.sleep(float(random.random() * random.randint(1,3)))
self.complete.emit(str(self.id))
self.finished.emit()
def main():
app = QApplication([])
ex = QWidget()
ex.show()
global scraperhost
scraperhost = ScraperHost(0, [], "index")
scraperhost.start()
app.exec_()
return
main()
问题来源StackOverflow 地址:/questions/59383422/half-of-threads-randomly-not-completing-and-vanishing
在旧的单处理器系统中,各个线程只是占用处理器的一段时间片,因此不会出现一个线程运行到一半的时候,另一个线程又开始。但是,现在的机器一般都是多处理器系统,实现了真正的并行运行,因此这种情况肯定是会发生的。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。