简体   繁体   English

当 PyQt4 中 QRunners 的 QThreadPool 执行完成时获取通知

[英]Get notification when QThreadPool of QRunners in PyQt4 have completed execution

I've got this quick and dirty test I setup where I'm running a thread of QRunners in a QThreadPool one by one in PyQt4 on Python 2.7.我已经设置了这个快速而肮脏的测试,我在 Python 2.7 上的 PyQt4 中一个接一个地在 QThreadPool 中运行 QRunners 线程。 Basically it looks like it's running fine, but the threads/pool don't seem to stop the QThreadPool once all threads have completed execution.基本上它看起来运行良好,但是一旦所有线程都完成执行,线程/池似乎不会停止 QThreadPool。

I'm wondering if it's as simple as returning some built in method from the QRunnable ( ProductImporter here) when it's done executing it's code, but I can't seem to find anything in the documentation.我想知道它是否像在执行完代码后从 QRunnable(此处为ProductImporter )返回一些内置方法一样简单,但我似乎在文档中找不到任何内容。

I'm moving some code over to this setup from a QThread structure, since I can't have concurrent threads running at the same time.我正在将一些代码从 QThread 结构移到这个设置中,因为我不能同时运行并发线程。

Any ideas on how I could have the ProductImportTasks aware that it's tasks have all completed, so I can execute more code afterwards, or after that class is called?关于如何让 ProductImportTasks 知道它的任务已全部完成的任何想法,以便我可以在之后或在调用该类之后执行更多代码? Any help would be greatly appreciated!任何帮助将不胜感激!

import sys
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QThreadPool, QObject, QRunnable, pyqtSignal

class WorkerSignals(QObject):
    productResult = pyqtSignal(str)

class ProductImporter(QRunnable):
    def __init__(self, product):
        super(ProductImporter, self).__init__()

        self.product = product
        self.signals = WorkerSignals()

    def run(self):
        self.signals.productResult.emit(self.product['name'])
        return

class ProductImportTasks(QObject):
    def __init__(self, products):
        super(ProductImportTasks, self).__init__()
        self.products = products
        self.pool = QThreadPool()
        self.pool.setMaxThreadCount(1)

    def process_result(self, product):
        return

    def start(self):
        for product in self.products:
            worker = ProductImporter(product)
            worker.signals.productResult.connect(view.text)
            self.pool.start(worker)

        self.pool.waitForDone()


class ViewController(QObject):
    def __init__(self, parent=None):
        super(ViewController, self).__init__(parent)

    #@pyqtSlot(str)
    def text(self, message):
        print "This is the view.text method: " + message
        return


if __name__ == "__main__":

    app = QApplication(sys.argv)
    view = ViewController()
    main = ProductImportTasks([{"name": "test1"}, {"name": "test2"}, {"name": "test3"}])
    main.start()
    sys.exit(app.exec_())

Here's what your script does:这是您的脚本的作用:

  1. calls main.start()调用main.start()
  2. creates runnables and starts threadpool创建可运行对象并启动线程池
  3. waits for all the runnables to finish等待所有 runnable 完成
  4. returns from main.start()main.start()返回
  5. starts the application event-loop启动应用程序事件循环

Once the event-loop has started, the signals that were emitted by the runnables will be processed, and the messages will be printed.一旦事件循环开始,由 runnables 发出的信号将被处理,并打印消息。 This is because signals sent across thread are queued by default.这是因为默认情况下,跨线程发送的信号是排队的。 Normally, signals are sent synchronously, and don't require a running event loop.通常,信号是同步发送的,不需要运行事件循环。

If you change the connection type of the signals, and add a few print statements, it should be clear what's going on:如果您更改信号的连接类型,并添加一些打印语句,应该很清楚发生了什么:

            worker.signals.productResult.connect(view.text, Qt.DirectConnection)
            self.pool.start(worker)

        self.pool.waitForDone()
        print('finished')
        ...

    main.start()
    print('exec')
    sys.exit(app.exec_())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM