0

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?

Community
  • 1
  • 1
Kadir Erdem Demir
  • 3,531
  • 3
  • 28
  • 39
  • 3
    You should provide a minimal working example. – hank Jan 27 '16 at 12:16
  • `deleteLater()` should be used to defer deletion of an object because it might still be needed - e.g. when you want to delete an object inside it's own slot. – Mohamad Elghawi Jan 27 '16 at 12:28
  • "But some how deleted work object still receiving signal "percentage complete" - Please clarify what you exactly see, add the code where it crashes and add a backtrace maybe. In your code, the work object is *emitting* percentageComplete, not receiving it. Signal/slot connections are destructed if the sender or the receiver are destroyed, so I don't see how your deleted worker can emit a signal. And in your case, delete should be the right thing. – Frank Osterfeld Jan 27 '16 at 12:44
  • 1
    Please re-read your own question, it doesn't seem to make sense. Why would `work` receive `it's own `percentageCompleted` signal? Also, I suspect you are doing threading somehow wrong. If you are using `QObject` instances in threading, then most likely you should not override `QThread`. – hyde Jan 27 '16 at 13:58
  • All you guys were right , reading my own question really helped. Problem was totally different and related with lamdba were not disconnecting automatically. Now what should I do with my question? How should I edit it to make something useful or at least not confusing. – Kadir Erdem Demir Jan 29 '16 at 14:37

4 Answers4

3

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

Community
  • 1
  • 1
Szymson
  • 990
  • 1
  • 13
  • 28
  • That disconnects all connections to signals of that object, not all signals connecting to slots of that object, which is what is required here. – 1313e Apr 24 '20 at 04:39
0

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.

0

Until unless you have some custom code, just use QThreaddirectly.

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

ramtheconqueror
  • 1,907
  • 1
  • 22
  • 35
0

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.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313