暂停 QThread 的 运行 方法来测试它

Pause the run method of a QThread to test it

我这样创建一个 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。所以 运行() 方法启动异步网络请求,然后完成。在这个阶段,线程通常会发送一个 "finished" 信号。但是异步web请求当然没有做。

在完成所有异步 Web 请求之前,我可以做什么来阻止 "finished" 信号?

我尝试在 运行() 方法的末尾使用 wait(),但我得到:

QThread::wait: Thread tried to wait on itself

我也试过sleep(),但是没有结果,'finished'信号还在。

有什么想法吗?

我无法重现,但我有一些注释可能会有所帮助:

可能发生的情况是所有异步任务在解释器到达行之前完成:

 while not self.exiting:

您假设异步调用会给您足够的时间在所有处理完成之前到达 while 语句。

另一方面,由于您使用的是 QtCore.QThread,您不需要控制变量来知道何时停止,您可以使用其中一个停止线程:QThread.exit, QThread.quit or QThread.terminate,请注意最后一个不推荐的。

关于 self.exiting 变成 True,这是非常罕见的,我不得不说,但是如果不执行行 self.exiting = True 就不可能发生这种情况(查看您的代码)我建议在那里设置一个断点并查看调用堆栈以跟踪导致该行被执行的调用路径。

另一个想法是设置一个 Hardware Breakpoit 以查看 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.