所有任务的单个工作线程还是多个特定的工作线程?

Single worker thread for all tasks or multiple specific workers?

我正在使用 PyQt5 创建一个简单的 GUI 应用程序,我从 API 请求一些数据,然后用于填充 UI 的各种控件。

我关注的关于 PyQt 工作线程的示例似乎都是子class QThread,然后在覆盖的 run() 方法中执行它们的业务逻辑。这工作正常,但我想使用工作人员在不同时间执行不同的 API 调用。

所以我的问题是:我是否需要为每个我想做的操作创建一个特定的工作线程,或者有没有办法让我可以使用一个线程 class 来执行不同的操作在不同的时间,因此避免了创建不同线程的开销 sub-classes?

你可以做的是设计一个对象来完成所有这些任务(为槽/信号继承 QObject)。假设每个任务都定义为一个单独的函数 - 让我们将这些函数指定为插槽。

然后(事件的一般顺序):

  • 实例化一个 QThread 对象。
  • 实例化你的class。
  • 使用 YouClass->moveToThread(pThread) 将您的对象移动到线程中。
  • 现在为每个插槽定义一个信号并将这些信号连接到对象中的相关插槽。
  • 最后 运行 线程使用 pThread->start()

现在您可以发出信号以在线程中执行特定任务。您不需要子 class QThread 只需使用从 QObject 派生的普通 class(这样您就可以使用 slots/signals)。

您可以在一个线程中使用一个 class 来执行多个操作(注意:它们将排队)。或者在很多线程中制作很多classes(到运行"parallel")。

我对 python 的了解还不够,无法在这里尝试举个例子,所以我不会:o

注意: sub-class QThread 的原因是如果您想扩展 QThread class 的功能 - 即添加 more/specific线程相关函数。 QThread 是一个 class 控制线程,并不意味着用于 运行 arbitrary/generic 任务...即使你 可以 滥用如果您愿意,可以这样做:)

这里是一个(但可以是任意多个)工作对象的简明示例,它被移动到单个 运行 QThread(已启动)并通过信号进行通信。线程也停止在最后。它演示了 code_fodder 在 中概述的内容。

from PyQt4 import QtCore
QtCore.Signal = QtCore.pyqtSignal

class Master(QtCore.QObject):

    command = QtCore.Signal(str)

    def __init__(self):
        super().__init__()

class Worker(QtCore.QObject):

    def __init__(self):
        super().__init__()

    def do_something(self, text):
        print('current thread id = {}, message to worker = {}'.format(int(QtCore.QThread.currentThreadId()), text))

if __name__ == '__main__':

    app = QtCore.QCoreApplication([])

    # give us a thread and start it
    thread = QtCore.QThread()
    thread.start()

    # create a worker and move it to our extra thread
    worker = Worker()
    worker.moveToThread(thread)

    # create a master object and connect it to the worker
    master = Master()
    master.command.connect(worker.do_something)

    # call a method of the worker directly (will be executed in the actual thread)
    worker.do_something('wrong way to communicate with worker')

    # communicate via signals, will execute the method now in the extra thread
    master.command.emit('right way to communicate with worker')

    # start the application and kill it after 1 second
    QtCore.QTimer.singleShot(1000, app.quit)
    app.exec_()

    # don't forget to terminate the extra thread
    thread.quit()
    thread.wait(5000)