我创建一个这样的Worker对象:
from PyQt4 import QtSql, QtCore
from requests_futures.sessions import FuturesSession
class Worker(QtCore.QThread):
def __init__(self):
QtCore.QThread.__init__(self)
self.exiting = False
self.list_urls = # Urls coming from somewhere
# List to store the urls of the pages to request
self.list_futures_urls = []
def __del__(self):
"""Method to destroy the thread properly"""
self.exiting = True
self.wait()
def run(self):
"""Main function. Starts the real business"""
print(self.exiting) # -> True !!!!!
session = FuturesSession(max_workers=10)
for url in self.list_urls:
future = session.get(url)
future.add_done_callback(completeData)
self.list_futures_urls.append(future)
# HERE !!!!! WHY ?
print(self.exiting) # -> True
self.exiting = False
print(self.exiting) # -> False
while not self.exiting:
self.sleep(20000)
# self.wait()
def completeData(self):
total_futures = self.list_futures_urls
# Checking if all the futures have started and finished
if len(total_futures) != len(self.list_urls):
return
else:
states_futures = []
for result in total_futures:
states_futures.append(result.done())
if False not in states_futures:
self.exiting = True
print("boum")
如您所见,我的worker是一个线程,并启动异步请求Session。因此run()方法启动异步Web请求,然后完成。在这个阶段,线程通常发送"完成"信号。但是异步Web请求当然没有完成。
我该怎样做才能阻止"完成"信号,直到所有异步Web请求完成?
我在run()方法结束时尝试使用wait(),但是得到了:
QThread::wait: Thread tried to wait on itself
我也尝试过sleep(),但没有结果,'完成了'信号仍在发出。
有什么想法吗?
答案 0 :(得分:1)
我无法重现,但我有一些可能有帮助的注释:
可能发生的事情是所有异步任务在解释器到达行之前完成:
while not self.exiting:
您假设异步调用会在所有处理完成之前为您提供足够的时间来到达while
语句。
另一方面,由于您使用的是QtCore.QThread
,因此您不需要控制变量来知道何时停止,您可以使用以下方法之一停止线程:QThread.exit,{{ 3}}或QThread.quit,请注意不推荐的最后一个。
关于self.exiting
成为True
,这非常罕见,我不得不说,但是如果不执行行self.exiting = True
我就不会发生这种情况(查看您的代码)我建议在那里设置断点并查看callstack以跟踪导致该行被执行的调用路径。
另一个想法是设置QThread.terminate以查看self.exiting
的值何时发生变化。
可行解决方案:
class Worker(QtCore.QThread):
# I don't test this code, is just for show
# the way to go.
def __init__(self):
QtCore.QThread.__init__(self)
self.list_urls = # Urls coming from somewhere
self.list_futures_urls = []
def run(self):
"""Main function. Starts the real business"""
session = FuturesSession(max_workers=10)
for url in self.list_urls:
future = session.get(url)
future.add_done_callback()
self.list_futures_urls.append(future)
while (True):
# You could add some sleep here in order to create a small delay between iterations.
# WARNING: You have to aware of the posibility that a result.get() call never returns True,
# in that this code (as well as yours) will run into an infinite loop/thread.
results = [result.done() for result in self.list_futures_urls]
if (False not in results):
self.exit()
# Callback removed from this code since the only purpose of
# it was to end the thread when all task get done.