Issue
I have the following code:
import time
from PyQt5.QtCore import QThread, QObject
from PyQt5.QtWidgets import QWidget, QApplication
class Worker(QObject):
def run(self):
time.sleep(1)
print("Worker is finished")
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.show()
self.thread = QThread()
self.worker = Worker()
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.run)
self.thread.finished.connect(self.on_thread_finished)
self.thread.start()
def on_thread_finished(self):
print("Thread finished")
self.thread.deleteLater()
if __name__ == "__main__":
app = QApplication([])
window = MainWindow()
app.exec_()
Run it, it shows the window, prints Worker is finished
, nothing more. That's weird. IMHO when the worker is finished, the thread should be finished too, which means the on_thread_finished
method should be called and Thread finished
should be printed. But it wasn't. Why?
Solution
when the worker is finished, the thread should be finished too
That's not how it works. Your Worker::run
method is being invoked as a slot
via the usual signal
/slot
mechanism after which the QThread
will continue to process events as normal.
If you want to terminate the QThread
when Worker::run
has completed you need to tell it to do so explicitly...
import time
from PyQt5.QtCore import Qt, QThread, QObject
from PyQt5.QtWidgets import QWidget, QApplication
class Worker(QObject):
# Constructor accepts the QThread as a parameter and stashes it
# for later use.
def __init__(self, thread):
super(Worker, self).__init__()
self.m_thread = thread
def run(self):
time.sleep(1)
print("Worker is finished")
# We're done so ask the `QThread` to terminate.
if self.m_thread:
self.m_thread.quit()
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.show()
self.thread = QThread()
# Pass the QThread to the Worker's ctor.
self.worker = Worker(self.thread)
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.run)
self.thread.finished.connect(self.on_thread_finished)
self.thread.start()
def on_thread_finished(self):
print("Thread finished")
self.thread.deleteLater()
if __name__ == "__main__":
app = QApplication([])
window = MainWindow()
app.exec_()
Very 'inelegant' but it conveys the idea.
A simpler alternative that springs to mind would be to simply make use of QThread::currentThread()
, in which case your Worker::run
method becomes...
class Worker(QObject):
def run(self):
time.sleep(1)
print("Worker is finished")
# We're done so ask the `QThread` to terminate.
QThread.currentThread().quit()
Answered By - G.M.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.