import sys import time from PySide2.QtCore import Slot, Signal, QThread, QObject from PySide2.QtWidgets import QApplication, QMainWindow, QLabel, QWidget, QVBoxLayout class ThreadWorker(QObject): finished = Signal() def __init__(self, target, *args, **kwargs): super().__init__(None) self.__target = target self.__args = args self.__kwargs = kwargs @Slot() def run(self): self.__target(*self.__args, **self.__kwargs) self.finished.emit() def create_thread(target, *args, dispose=False, parent=None, **kwargs): thread = QThread(parent) worker = ThreadWorker(target, *args, **kwargs) worker.moveToThread(thread) thread.started.connect(worker.run) worker.finished.connect(thread.quit) if dispose: worker.finished.connect(worker.deleteLater) thread.finished.connect(thread.deleteLater) # Make the worker an attribute of the thread to stop Python from garbage collecting it. # https://stackoverflow.com/a/63274024/2512078 thread.worker = worker return thread class ExampleMainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.setCentralWidget(QWidget(self)) self.centralWidget().setLayout(QVBoxLayout(self.centralWidget())) self.label = QLabel("If you see this immediately, the thread did not block.", self.centralWidget()) self.centralWidget().layout().addWidget(self.label) self.test_thread = create_thread(self.long_running_task, parent=self) self.test_thread.start() @staticmethod def long_running_task(): print("Task started.") time.sleep(10) print("Task finished.") if __name__ == "__main__": app = QApplication(list()) window = ExampleMainWindow() window.show() sys.exit(app.exec_())