Python/PySide: How can i destroy a terminated thread object?
You're right, your problem is, that your object is not deleted. You delete only the reference self.new_thread
. The problem is in this line:
self.new_thread = thread_worker(self)
The reason for this is that the parent self
of the thread is alive. As long as parent stays alive, the object self.new_thread
is not destroyed. Try something like this:
self.threadParent = QObject()
self.new_thread = thread_worker(self.threadParent)
And now you also delete the parent self.threadParent
:
self.new_thread.terminate()
del(self.new_thread)
del(self.threadParent)
Your signals should be disconnected now.
You don't need the following line, because the object self.new_thread
has been already deleted after you emit the signal stop_thread_signal
:
#self.terminate() # does it works at this place?
Igor
Updated on June 04, 2022Comments
-
Igor almost 2 years
I would like to implement a button to stop a thread with a process, it works but not as expected: i can't delete the thread object. (EDIT: The reference to the thread object seems to be deleted, but the signals are not disconnected automatically by deleting the thread object, i can access it anyway via the signal.)
I have a modul with a class thread_worker and a function for complex processing which is running as process:
from PySide.QtCore import * from PySide.QtGui import * import multiprocessing as mp import time # this function runs as a process def complex_processing(queue): # do something ... class thread_worker(QThread): message_signal = Signal(str) stop_thread_signal = Signal() def __init__(self, prozessID, sleepTime, parent=None): super(ThreadProzessWorker, self).__init__(parent) self.queue = mp.Queue() self.process = mp.Process(target=complex_processing, args=(self.queue,)) self.timeStamp = int(time.time()) def run(self): self.process.start() self.process.join() @Slot() def stop_process_and_thread(self): if self.isRunning(): self.message_signal.emit("Thread %d is running!" % self.timeStamp) if self.process.is_alive(): self.process.terminate() self.process.join() self.stop_thread_signal.emit() #self.terminate() # does it works at this place? else: self.message_signal.emit("Thread %d is not running!" % self.timeStamp)
I have two buttons in my application to create/run and terminate a thread object.
... ... # Buttons self.button_start_thread = QPushButton("Start Thread") self.button_start_thread.clicked.connect(self.start_thread) self.button_stop_thread = QPushButton("Stop Thread") ... ... @Slot() def start_thread(self): self.new_thread = thread_worker(self) self.button_stop_thread.clicked.connect(self.new_thread.stop_process_and_thread) self.new_thread.stop_thread_signal.connect(self.stop_thread) self.new_thread.message_signal.connect(self.print_message) .... .... @Slot() def stop_thread(self): self.new_thread.terminate() #self.button_stop_thread.disconnect(self.new_thread) del(self.new_thread) @Slot(str) def print_message(self, message): print(message) ... ...
If i start and stop the first thread - it works fine and terminate, but if i klick on the 'Stop'-Button again the output is:
Thread 1422117088 is not running!
I don't understand it: the object
self.new_thread
is deleted bydel(self.new_thread)
or not? How can i access this object if it was deleted? If i start and stop again a new thread, the output is:Thread 1422117088 is not running! # not expected, the thread object is deleted! Thread 1422117211 is running! # expected
Now i do it again (start and stop), the output is:
Thread 1422117088 is not running! # not expected, the thread object is deleted! Thread 1422117211 is not running! # not expected, the thread object is deleted! Thread 1422117471 is running! # expected
and so on...
First question: I don't understand why the old threads are not deleted? Why i can access them? I think it is not good: my application crashes at some point, if there are too many threads (not deleted objects) in the background.
Second question: I dont't understand why the signals are not disconnected if i delete the object
self.new_thread
? I don't want to disconnect the signals manually: if i have many signals i can forgot to disconnect some signals.Third question: I choose this way to stop a thread with one process. Is there another way to do this better?
UPDATE:
The thread object appears to be destroyed:
del(self.new_thread) print(self.new_thread) Output: AttributeError: 'MainWindow' object has no attribute 'new_thread'
But my signals are not disconnected!? Here is described that: "A signal-slot connection is removed when either of the objects involved are destroyed." It does not work in my code.