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.
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.
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?
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.
Then (a general order of events):
YouClass->moveToThread(pThread)
.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).
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
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 :)
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With