2016-02-25 19:10 GMT+01:00 Elvis Stansvik <elvst...@gmail.com>:
> 2016-02-25 18:24 GMT+01:00 Murphy, Sean <smur...@walbro.com>:
>>> >    Foo() : QObject(nullptr) {
>>> >       moveToThread(&m_thread);
>>> >       m_thread.start();
>>> >    }
>>> >
>>> >    ~Foo() {
>>> >       m_thread.quit();
>>> >       m_thread.wait();
>>> >    }
>>>
>>> This destructor is either never run or deadlocks.
>>>
>>> A QObject can only be destroyed in its thread of affinity. So the above is
>>> running in that m_thread thread, which means it hasn't exited. Waiting for 
>>> it
>>> to exit will wait forever.
>>
>> Just when I think I have QObjects and QThreads figured out, I realize I 
>> don't... How do I correctly handle my situation?
>>
>> I've got a QObject-based class that talks to a custom device and needs to 
>> block while making reads/writes to that device. This thread runs the entire 
>> duration of my application, because the work it's doing never finishes, it 
>> just monitors the device for messages and notifies my UI class when data 
>> comes in.
>>
>> So currently I'm doing this:
>>
>> myGUIObject.h:
>> private:
>>   myBlockingObject* blocking;
>>   QThread* thread;
>>
>> myGUIObject.cpp:
>> myGUIObject()
>> {
>>   thread = new QThread(this);
>>   blocking = new myBlockingObject();
>>   blocking->moveToThread(thread);
>> }
>>
>> How/where do I properly delete "blocking"? Right now I'm doing this:
>> ~myGUIObject()
>> {
>>     thread->exit();
>>     blocking->deleteLater();
>> }
>>
>> But Thiago's comment "A QObject can only be destroyed in its thread of 
>> affinity" sounds like it's not the right way to do it?
>> Sean
>
> I was in a similar situation some years ago, talking to a USB/serial
> device in a separate thread. I had a look at the code, and what I did
> back then was to connect the finished signal of the thread to the
> deleteLater() slot of the object I had moved to the thread. I actually
> did the same with the thread itself. So the connect() calls I did to
> ensure cleanup looked something like this:
>
>     // Connect to thread signals to start the sensor and clean up.
>     connect(m_sensorThread, SIGNAL(started()), sensor, SLOT(start()));
>     connect(m_sensorThread, SIGNAL(finished()), sensor, SLOT(deleteLater()));
>     connect(m_sensorThread, SIGNAL(finished()), m_sensorThread,
> SLOT(deleteLater()));
>
> Where sensor is the object I had previously moved to m_senseorThread.
>
> Not sure if your approach above with calling deleteLater() explicitly
> and immediately after thread->exit() is right or wrong, or if doing it
> by signal/slot connections like I did is any better. Just thought I
> would chime in :)

I see now that this technique is actually right there in the QThread
docs, under "Managing Thread", third paragraph [1]:

"From Qt 4.8 onwards, it is possible to deallocate objects that live
in a thread that has just ended, by connecting the finished() signal
to QObject::deleteLater()."

So I think this is the approach you should use.

The initial example in the class docs also shows the "suicide"
approach of destructing the thread itself:

    connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);

In the example you gave, I think you're leaking the thread.

Cheers,
Elvis

[1] http://doc.qt.io/qt-5/qthread.html#managing-threads

>
> Elvis
>
>> _______________________________________________
>> Interest mailing list
>> Interest@qt-project.org
>> http://lists.qt-project.org/mailman/listinfo/interest
_______________________________________________
Interest mailing list
Interest@qt-project.org
http://lists.qt-project.org/mailman/listinfo/interest

Reply via email to