문제

In order to ease my cleanup efforts, I want to set the parent of my worker object to be the Qthread to which it is moved. (See below).

void TelnetServer::incomingConnection(qintptr socketDescriptor)
{
    QThread * TelnetConnectionThread = new QThread(this);
    TelnetConnection *worker = new TelnetConnection(socketDescriptor,TelnetConnectionThread);
    connect(TelnetConnectionThread, SIGNAL(started()), worker, SLOT(start()));
    connect(TelnetConnectionThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
    worker->moveToThread(TelnetConnectionThread);  // Move worker into QThread
    TelnetConnectionThread->start();  
}

Right before the start() line, I added:

worker->setParent(TelnetConnectionThread);

but at runtime I see an error that I can't do that because the new parent is in a different thread. How can that be? In the line above I moved the worker to the new thread...so the worker should be in the same thread as the TelnetConnectionThread. Help?


I confirmed with some qDebug's and thread() that the worker does in fact get moved to the new thread!

도움이 되었습니까?

해결책

I think you're a bit confused about QThread. The first problem is that its name is rather misleading as it's not actually a thread, but a thread controller. Next is the issue of thread affinity (the thread that an object is actually running on).

If we start in the main thread and create a new QThread, the thread controller is instantiated in the main thread: -

QThread* pThread = new QThread;

Next the thread is started: -

pThread->start();

Even though pThread is thought to be running in a different thread, its thread affinity is still the main thread, but any QObject-based class instance that gets moved to pThread will have the thread affinity of the new thread: -

QObject* pObject = new QObject;
pObject->moveToThread(pThread);

Still, pThread's thread affinity is the main thread, while pObject's thread affinity is the new thread; remember, pThread is actually a thread controller!

To set the parent of pObject to be pThread would be wrong, as they have different thread affinity. This is a problem that many people encounter when trying to inherit from QThread, rather than using it as a separate entity and moving QObjects to it. What usually happens is that objects are sometimes created in the constructor of their inherited QThread class, without parenting them and not realising that those objects will have the thread affinity of the main thread, not the new thread as they expect.

Moving a QObject to another thread also moves its children, so trying to set the parent as the thread (thread controller!) does not make sense.

To summarise, you cannot set the parent of your worker object to be the TelnetConnectionThread, as they run on different threads.

However, if you're trying to have the thread cleanup after itself when finished, you can do this: -

connect(TelnetConnectionThread, SIGNAL(finished()), TelnetConnectionThread, SLOT(deleteLater()));
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top