Reputation: 3605
In this topic it told when a qobject deleted its active connections will be deleted. I have a case like below:
Work* work = new Work();//->Work derived from QObject
Worker* worker = new Worker(work);//->Worker derived from QThread and has the ownership of work
connect(work, SIGNAL(percentageComplete(int)), progressDialog, SLOT(setValue(int)));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
progressDialog->show();
worker->start();
In worker's destructor I have :
Worker::~Worker(void){
if(work != nullptr){
work->deleteLater();
}
}
I am %100 sure that work is deleted. I can see it with a breakpoint. I can even see QObjects desctructor call.
But some how deleted work object still receiving signal "percentage complete". And because it is deleted ,causing a crush.
I want to ask why signals are not disconnected even object is deleted?
A second question in Worker's destructor work->deleteLater();
or delete work;
is correct?
Upvotes: 0
Views: 3295
Reputation: 98505
This happens because there are two threads attempting to use Work
at the same time, with no apparent synchronization, with predictably bad results.
You have to marshal the ownership of and access to Work
between the main thread and the worker thread, so that the two threads can't access it at the same time in an unsafe manner.
The destructor of Worker
is not executed in the Worker
thread! Furthermore, I don't see any code that prevents that destructor from running while the Worker
thread is still active. Note that a QThread
is not a thread, but a thread handle. It's a deceptive name.
Alas, your question can't be answered without seeing a complete example that reproduces the issue.
Upvotes: 0
Reputation: 1964
Until unless you have some custom code, just use QThread
directly.
Work* work = new Work(); // no parent
QThread* thread = new QThread();
work->moveToThread(worker);
connect(thread, SIGNAL(started()), work, SLOT(doSomeWork())); // add this function doSomething() in Work class which on completion should emit finished() signal
connect(work, SIGNAL(finished()), thread, SLOT(quit())); // quit the thread
connect(work, SIGNAL(finished()), work, SLOT(deleteLater())); // delete work after job done
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); // delete thread
// if you are using c++11, do this to see Work and Thread deletion
connect(work, &Work::destroyed, [](){ qDebug() << "Work object deleted"; });
connect(thread, &QThread::destroyed, [](){ qDebug() << "Thread deleted"; });
// start the thread now
thread->start();
See here for more info on QThread usage
Upvotes: 0
Reputation: 1132
Why dont you use disconnect() for disconnect all connected slots/signals ? You can call this function in destructor.Here you have solution from similar topic
Upvotes: 3
Reputation: 1
My guess is that the work object is moved to the worker thread, and that the signal emitted will end up on the event loop, which can be delivered a bit later. Probably you have killed progressDialog at that point.
Upvotes: 0