Multithreading PyQt applications with QThreadPool
Last updated on:2 years ago
A common problem when building Python GUI applications is “locking up” of the interface when attempting to perform long-running background tasks.
MultiThreading
The solution is simple: get your work out of the GUI thread (and into another thread). PyQt (via Qt) provides an straightforward interface to do exactly that.
If you take a step back and think about what you want to happen in your application, it can probably be summed up with “stuff to happen at the same time as other stuff happens”.
Threads share the same memory space, so are quick to start up and consume minimal resources. Processes use separate memory space (and an entirely separate Python interpreter). This side-steps any potential problems with the GIL, but at the cost of slower start-up times, larger memory overhead and complexity in sending/receiving data.
QRunnable and QThreadPool. The former is the container for the work you want to perform, while the latter is the method by which you pass that work to alternate threads.
Code
Worker setting up:
class WorkerSignals(QObject):
# finished = pyqtSignal()
error = pyqtSignal(tuple)
result = pyqtSignal(object)
progress = pyqtSignal(int)
class Worker(QThread):
# Pass data into the exicution function
def __init__(self, fn, *args, **kwargs):
super(Worker, self).__init__()
self.fn = fn
self.args = args
self.kwargs = kwargs
self.signals = WorkerSignals()
@pyqtSlot()
def run(self):
try:
result = self.fn(*self.args, **self.kwargs)
except:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit((exctype, value, traceback.format_exc()))
else:
self.signals.result.emit(result)
Start thread:
self.ThreadTrain = Worker(self.doTrain)
self.ThreadTrain.start()
Terminate thread:
self.ThreadTrain.terminate()
Reference
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!