Qt/C++将worker的parent更改为qthread失败

TSG*_*TSG 1 c++ qt multithreading move qobject

为了简化我的清理工作,我想将我的worker对象的父对象设置为它所移动的Qthread.(见下文).

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();  
}
Run Code Online (Sandbox Code Playgroud)

在start()行之前,我添加了:

worker->setParent(TelnetConnectionThread);
Run Code Online (Sandbox Code Playgroud)

但在运行时我看到一个错误,我无法做到这一点,因为新的父级在不同的线程.怎么可能?在上面的行中,我将worker移动到新线程...因此worker应该与TelnetConnectionThread位于同一个线程中.救命?


我确认了一些qDebug和thread()工作者实际上已经转移到了新的线程!

The*_*ght 5

我觉得你对QThread有点困惑.第一个问题是它的名称相当误导,因为它实际上不是一个线程,而是一个线程控制器.接下来是线程关联性问题(对象实际运行的线程).

如果我们从主线程开始并创建一个新的QThread,则在线程中实例化线程控制器: -

QThread* pThread = new QThread;
Run Code Online (Sandbox Code Playgroud)

接下来线程启动: -

pThread->start();
Run Code Online (Sandbox Code Playgroud)

即使pThread被认为是在不同的线程中运行,它的线程亲和性仍然是线程,但任何移动到pThread的基于QObject的类实例都将具有新线程的线程亲和性: -

QObject* pObject = new QObject;
pObject->moveToThread(pThread);
Run Code Online (Sandbox Code Playgroud)

仍然,pThread的线程亲和力是线程,而pObject的线程亲和力是新线程; 记住,pThread实际上是一个线程控制器!

将pObject的父节点设置为pThread是错误的,因为它们具有不同的线程亲和性.这是许多人在尝试从QThread继承时遇到的问题,而不是将其用作单独的实体并将QObject移动到它.通常会发生的事情是,对象有时是在其继承的QThread类的构造函数中创建的,没有对它们进行父化,也没有意识到这些对象将具有主线程的线程亲和性,而不是他们期望的新线程.

将QObject移动到另一个线程也会移动它的子节点,因此尝试将父节点设置为线程(线程控制器!)没有意义.

总而言之,您不能将工作对象的父级设置为TelnetConnectionThread,因为它们在不同的线程上运行.

但是,如果您在完成后尝试自行清理线程,则可以执行以下操作: -

connect(TelnetConnectionThread, SIGNAL(finished()), TelnetConnectionThread, SLOT(deleteLater()));
Run Code Online (Sandbox Code Playgroud)