【问题标题】:get response or signal when all threads are complete当所有线程都完成时获得响应或信号
【发布时间】:2023-03-25 03:35:01
【问题描述】:

使用 GUI 我正在复制多个文件。对于每个文件,我正在启动一个线程。有没有一种方法可以让我得到一个信号或响应,告诉所有线程都完成了他们的工作。我需要响应,因为根据所有线程完成后的响应,我想启用/禁用 GUI 上的几个按钮和复选框。

for file_name in _src_files:
    if (os.path.exists(_full_file_name)):
        t = Thread(target=file_util.copy_file, args=[_full_file_name, _str_destination_dir, 'update=1'])
        t.start()

【问题讨论】:

    标签: python multithreading pyqt pyqt4


    【解决方案1】:

    您必须创建一个继承自QObject 并具有自定义信号的类,例如:

    def copy_file(source, destination, message, log):
        [...]
        log.finished.emit()
    

    class Logger(QObject):
        finished = pyqtSignal()
    

    self.l = Logger()
    for file_name in _src_files:
        if (os.path.exists(_full_file_name)):
            t = Thread(target=file_util.copy_file, args=[_full_file_name, _str_destination_dir, 'update=1'], self.l)
            t.start()
    self.l.finished.connect(some_slot)
    

    例子:

    import time
    from threading import Thread
    import sys
    
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *
    
    class Logger(QObject):
        finished = pyqtSignal(str)
    
    def myfunc(i, log):
        print("sleeping 5 sec from thread %d" % i)
        time.sleep(5)
        print("finished sleeping from thread %d" % i)
        log.finished.emit("message %d" % i)
    
    
    class Widget(QWidget):
        def __init__(self, *args, **kwargs):
            QWidget.__init__(self, *args, **kwargs)
            self.l = Logger()
            self.counter_threads = 0
            for i in range(10):
                t = Thread(target=myfunc, args=(i, self.l))
                t.start()
                self.counter_threads += 1
            self.l.finished.connect(self.some_slot)
    
        def some_slot(self, message):
            print("some_slot: "+ message)
            self.counter_threads -= 1
            if self.counter_threads == 0:
                print("finished all threads")
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 谢谢回复。由于我是 python 新手,我需要澄清一下,当我在循环之后调用 self.l.finished.connect(some_slot) 时,正如你所说,它只会在所有线程完成时运行 some_slot 一次,或者在每个线程之后调用它线程完成。其次 some_slot 可能是同一类的函数?谢谢
    • 第一: 每次调用emit()都会执行,也就是说对于每个线程,根据你的评论表示你要传递一个结果,如果是这样,它是一个什么样的结果? 第二: some_slot 可以是类的成员。
    • 我实际上应该只在最后一个线程完成时发出。所以我可以从发射中知道所有线程都完成了
    • 一般来说,我认为所有线程都不会做同样的工作,因为例如一个线程可以复制比另一个线程更多的信息,因此首先开始的线程不一定首先结束,但是如果你想要要知道是否所有线程都已完成解决方案很简单:使用计数器。稍后我将向您展示一个示例。
    • @latlong 我已经更新了我的答案,如果我的答案对您有帮助,请不要忘记将其标记为正确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-04
    • 1970-01-01
    • 2023-03-29
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多