PDA

View Full Version : when can I delete a thread?



mastupristi
10th September 2010, 22:58
In a project I use Qthreads. Some actions are triggered by clicking a button, and are executed from a thread (to lete interfac be responsive during actions executions)

I have attached a little example to figure out my doubt
5164

I have this dialog:
5163

When the button is clicked is called the following slot:

void Dialog::slotBtn(void)
{
// MyThread *myt; // declared in the class
myt = new MyThread;

myt->start();
}

where MyThread is:

#include <QThread>

class MyThread : public QThread
{
public:
MyThread();

void run(void);
};

MyThread::MyThread()
{
}


void MyThread::run(void)
{
// some stuff that can takes some time
sleep(1);

qWarning("hallo world from MyThread");
//end of thread
}

I wonder when to delete myt.

For example, when a thread finish a signal QThread::finished() is emitted. I can connect to a slot, but I wonder if it is safe to delete it inside that slot.

thanks

Talei
10th September 2010, 23:42
The way I would do that is:



void Dialog::slotBtn(void)
{
// MyThread *myt; // declared in the class - on stack
myt = new MyThread;
connect( myt, SIGNAL(finished()), this, SLOT(mytFinishedSlot()));
button->setEnabled(false); //to prevent running again the same thread
myt->start();
}

void Dialog::mytFinishedSlot(){
//retrieve the data from the thread
disconnect( myt, SIGNAL(finished()), this, SLOT(mytFinishedSlot()));
delete myt;
button->setEnabled(true); //"turn one" button
}
Comments and critique are more then welcome.

wysota
10th September 2010, 23:54
Comments and critique are more then welcome.
It would crash your application. You can't delete an object from within a slot connected to a signal emitted by the same object. But you can use deleteLater(). And you don't have to disconnect the signal/slot connection - it will be done automatically when one of the objects involved in the connection is destroyed.

Talei
11th September 2010, 01:14
Simple example and two errors... eh.
I tested this code and It didn't crash application, so I'm a little bit confused about that.
Please correct me, as I'm self taught and can misunderstand some aspect of signal/slot mechanism.
I use disconnect to ensure that object is not connected to anything before delete, and at that point object should have no connection, and then simply delete the object, so the slot is not wired to anything and AFAIK should be treat as function (this is how I understand it from the docs, so probably I understand it wrong).

Also I just look at the qcoreapplication.cpp post event (because logically there must be the difference between delete and deletelater()), that is executed with deletelater() and from what I can understand:
when I use delete object, I delete only the object and event are still in mem.?
when deletelater() is used, I delete not only the object but also all the events associated with this object?
Or I'm completely mistaken with this?

wysota
11th September 2010, 09:54
I tested this code and It didn't crash application, so I'm a little bit confused about that.
Because it depends on the context. Notice that there may be another slot connected to the same signal and if your slot is ran before the other one, the crash is bound to occur.


I use disconnect to ensure that object is not connected to anything before delete, and at that point object should have no connection, and then simply delete the object, so the slot is not wired to anything and AFAIK should be treat as function (this is how I understand it from the docs, so probably I understand it wrong).
A slot is a regular method and you don't have to do anything for it to be treated this way. If you are in a context of a function that will delete the object, no more signals will be delivered to the object and the method will not be called as a slot again. But this is irrelevant. What is relevant is that the destructor of QObject will remove all the connections itself.


when I use delete object, I delete only the object and event are still in mem.?
I don't know what you mean by that. I don't know if it answers your question but deleteLater() is a so called "deferred deletion" which will be deferred furhter if there are events pending for the object in the event queue so all pending events will be delivered prior to the actual destruction of the object. In case of a simple delete all pending events will be removed from the queue (if not immediately then during the next sweep of the event queue).

Talei
11th September 2010, 21:07
What confuses me about QThread and delete from within slot is that, finished() is emited after thread event loop stops(I assume that after this signal it is guaranteed that qthread event loop stops immediately - please read * ). At this point execution of thread ended and there is no pending event's inside QThread (in case presented above, of course there can be some pending user event's that needs to be dealt with ). So I assumed that I can delete that QThread object because there is no pending events (to ensure that this is true I manually disconnect object ).

*Or when finished() is emited event loop, depending on the i.e. CPU load, is still running, but it's event loop is queued to stop, so deleting qthread within finished() slot will actually crash app, because event loop of qthread didn't stooped yet,of course this is if'y situation depending on the various factors like cpu load, app context, etc..

So as far as I understand correct way of deleting qobject, in this case qthread, is to:

void Dialog::slotBtn(void)
{
// MyThread *myt; // declared in the class - on stack
myt = new MyThread;
connect( myt, SIGNAL(finished()), this, SLOT(mytFinishedSlot()));
button->setEnabled(false); //to prevent running again the same thread
myt->start();
}

void Dialog::mytFinishedSlot(){
//retrieve the data from the thread
myt.deleteLater();
button->setEnabled(true); //"turn one" button
}

tbscope
12th September 2010, 08:12
What confuses me about QThread and delete from within slot is that, finished() is emited after thread event loop stops(I assume that after this signal it is guaranteed that qthread event loop stops immediately - please read * ). At this point execution of thread ended and there is no pending event's inside QThread (in case presented above, of course there can be some pending user event's that needs to be dealt with ). So I assumed that I can delete that QThread object because there is no pending events (to ensure that this is true I manually disconnect object ).

Ahh this is the classical QThread mistake. A QThread object lives in the main thread. It makes use of the main thread event loop.
However, QThread launches a new thread with its own eventloop.


+---------------------------------+
| QThread |
| |
| Lives in the main thread. |
| Uses the main thread event loop |
| |
| +-----------------------------+ |
| | Thread | |
| | Has own eventloop | |
| +-----------------------------+ |
| |
+---------------------------------+

When a thread is finished, it doesn't mean the QThread object can't or will not receive events from the main thread. There are some perfectly sound examples where your thread can emit the finished signal and the QThread object can receive a new event or signal to restart the thread again.

Edit:


no pending events (to ensure that this is true I manually disconnect object)
And: disconnecting an object doesn't mean the object can not receive events.

Talei
12th September 2010, 09:31
I read so much about QThread, and I knew that QThread is not actual thread but still made such a mistake... eh there is a long way to go for me :o.
And when I looked at Your chart it came back to me immediately :), and right now I got a bigger picture of QThread.

Thanks you guys for wasting Your valuable time to answering my questions.