所有任务或多个特定工作人员的单个工作线程?

时间:2023-01-31 16:57:32

I'm creating a simple GUI application using PyQt5 where I request some data from an API which is then used to populate various controls of the UI.

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

The examples I was following about worker threads in PyQt all seem to sub-class QThread and then do their business logic in the overridden run() method. This works fine but I want to execute different API calls at different times using a worker.

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

So my question is: do I need to create a specific worker thread for every operation I wish to do or is there a way of having a single thread class that I can use to carry out different operations at different times and therefore avoid the overhead of creating different thread sub-classes?

所以我的问题是:我是否需要为我希望做的每个操作创建一个特定的工作线程,或者是否有一种方法可以使用单个线程类来在不同的时间执行不同的操作,从而避免开销创建不同的线程子类?

2 个解决方案

#1


8  

What you can do is design an object to do all these tasks (inherit QObject for slots / signals). Lets say each task is defined as a separate function - lets designate these functions as slots.

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

Then (a general order of events):

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

  • instantiate a QThread object.
  • 实例化QThread对象。

  • instantiate your class.
  • 实例化你的班级。

  • Move your object into the thread using YouClass->moveToThread(pThread).
  • 使用YouClass-> moveToThread(pThread)将对象移动到线程中。

  • Now define a signal for each slot and connect these signals to the relevant slots in your object.
  • 现在为每个插槽定义一个信号,并将这些信号连接到对象中的相关插槽。

  • Finally run the thread using pThread->start()
  • 最后使用pThread-> start()运行线程

Now you can emit a signal to do a particular task in the thread. You do not need to sub-class QThread just use a normal class derived from QObject (so that you can use slots/signals).

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

You can either use one class in one thread to do many operations (note: they will be queued). Or make many classes in many threads (to run "parallel").

您可以在一个线程中使用一个类来执行许多操作(注意:它们将排队)。或者在许多线程中创建许多类(以“并行”运行)。

I don't know python well enough to attempt an example here so I won't :o

我不太清楚python在这里尝试一个例子所以我不会:o

Note: The reason to sub-class QThread would be if you wanted to extend the functionality of the QThread class - i.e. add more/specific thread-related functions. QThread is a class that controls a thread, and is not meant to be used to run arbitrary/generic tasks... even though you can abuse it to do so if you wish :)

注意:如果你想扩展QThread类的功能 - 即添加更多/特定的线程相关函数,那么子类QThread的原因就是如此。 QThread是一个控制线程的类,并不打算用于运行任意/通用任务......即使你可以滥用它,如果你愿意:)

#2


4  

Here is a concise example of one (but could be as many as you wish) worker object which is moved to a single running QThread (started) and is communicating via signals. Also the thread is stopped at the end. It demonstrates what code_fodder outlined in his answer.

下面是一个简洁的示例(可能是您希望的多个)工作对象,它被移动到单个正在运行的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)

#1


8  

What you can do is design an object to do all these tasks (inherit QObject for slots / signals). Lets say each task is defined as a separate function - lets designate these functions as slots.

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

Then (a general order of events):

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

  • instantiate a QThread object.
  • 实例化QThread对象。

  • instantiate your class.
  • 实例化你的班级。

  • Move your object into the thread using YouClass->moveToThread(pThread).
  • 使用YouClass-> moveToThread(pThread)将对象移动到线程中。

  • Now define a signal for each slot and connect these signals to the relevant slots in your object.
  • 现在为每个插槽定义一个信号,并将这些信号连接到对象中的相关插槽。

  • Finally run the thread using pThread->start()
  • 最后使用pThread-> start()运行线程

Now you can emit a signal to do a particular task in the thread. You do not need to sub-class QThread just use a normal class derived from QObject (so that you can use slots/signals).

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

You can either use one class in one thread to do many operations (note: they will be queued). Or make many classes in many threads (to run "parallel").

您可以在一个线程中使用一个类来执行许多操作(注意:它们将排队)。或者在许多线程中创建许多类(以“并行”运行)。

I don't know python well enough to attempt an example here so I won't :o

我不太清楚python在这里尝试一个例子所以我不会:o

Note: The reason to sub-class QThread would be if you wanted to extend the functionality of the QThread class - i.e. add more/specific thread-related functions. QThread is a class that controls a thread, and is not meant to be used to run arbitrary/generic tasks... even though you can abuse it to do so if you wish :)

注意:如果你想扩展QThread类的功能 - 即添加更多/特定的线程相关函数,那么子类QThread的原因就是如此。 QThread是一个控制线程的类,并不打算用于运行任意/通用任务......即使你可以滥用它,如果你愿意:)

#2


4  

Here is a concise example of one (but could be as many as you wish) worker object which is moved to a single running QThread (started) and is communicating via signals. Also the thread is stopped at the end. It demonstrates what code_fodder outlined in his answer.

下面是一个简洁的示例(可能是您希望的多个)工作对象,它被移动到单个正在运行的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)