【问题标题】:Get notification when QThreadPool of QRunners in PyQt4 have completed execution当 PyQt4 中 QRunner 的 QThreadPool 完成执行时获取通知
【发布时间】:2015-12-30 02:11:30
【问题描述】:

我已经设置了这个快速而肮脏的测试,我在 Python 2.7 上的 PyQt4 中一个一个地在 QThreadPool 中运行 QRunners 线程。基本上它看起来运行良好,但是一旦所有线程完成执行,线程/池似乎并没有停止 QThreadPool。

我想知道它是否像在执行完代码后从 QRunnable(此处为ProductImporter)返回一些内置方法一样简单,但我似乎在文档中找不到任何内容。

我正在将一些代码从 QThread 结构移至此设置,因为我不能同时运行并发线程。

关于如何让 ProductImportTasks 知道它的任务已全部完成,以便我可以在之后或在调用该类之后执行更多代码的任何想法?任何帮助将不胜感激!

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_())

【问题讨论】:

    标签: python multithreading qt pyqt pyqt4


    【解决方案1】:

    这是您的脚本的作用:

    1. 致电main.start()
    2. 创建可运行对象并启动线程池
    3. 等待所有可运行对象完成
    4. main.start()返回
    5. 启动应用程序事件循环

    一旦事件循环开始,由可运行对象发出的信号将被处理,并且消息将被打印。这是因为跨线程发送的信号默认是排队的。通常,信号是同步发送的,不需要运行事件循环。

    如果更改信号的连接类型,并添加一些打印语句,应该清楚发生了什么:

                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_())
    

    【讨论】:

    • 啊哈,看起来真的都是信号连接类型——在这种情况下是同步与异步。我不得不暂时离开这个项目,所以我将不得不坐下来查看同步与异步在这种情况下是否有效,但现在我认为这应该有效,谢谢!
    猜你喜欢
    • 2014-03-27
    • 2010-11-06
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    • 2020-04-08
    • 1970-01-01
    • 2019-05-11
    • 2013-07-26
    相关资源
    最近更新 更多