Qt/C++ 将 worker 的父级更改为 qthread 失败
Posted
技术标签:
【中文标题】Qt/C++ 将 worker 的父级更改为 qthread 失败【英文标题】:Qt/C++ Change parent of worker to qthread fails 【发布时间】:2013-10-10 15:30:52 【问题描述】:为了减轻我的清理工作,我想将我的工作对象的父对象设置为它被移动到的 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();
在 start() 行之前,我添加了:
worker->setParent(TelnetConnectionThread);
但在运行时我看到一个错误,我不能这样做,因为新的父级在不同的线程中。怎么可能?在上面的行中,我将工作线程移到了新线程……所以工作线程应该与 TelnetConnectionThread 在同一个线程中。帮忙?
我通过一些 qDebug's 和 thread() 确认工作线程确实被转移到了新线程!
【问题讨论】:
你应该在连接插槽之前移动到线程,它确保连接是正确的类型 @ratchetfreak 怎么样?连接类型在信号发出时确定。 @thuga 我的错我的印象是 AutoConnection 在连接时被转换为直接或队列 @ratchetfreak 是的,我也这么认为了很长时间。我不确定我从哪里得到这些信息,但我确定我在某个地方读到过它。但后来我注意到在 Qt 文档中它说:The type of connection is determined when the signal is emitted.
.
【参考方案1】:
我认为您对 QThread 有点困惑。第一个问题是它的名字相当具有误导性,因为它实际上不是一个线程,而是一个线程控制器。接下来是线程亲和性问题(对象实际运行的线程)。
如果我们从主线程开始并创建一个新的QThread,线程控制器在main线程中被实例化:-
QThread* pThread = new QThread;
接下来启动线程:-
pThread->start();
即使 pThread 被认为在不同的线程中运行,它的线程亲和性仍然是 main 线程,但是任何移动到 pThread 的基于 QObject 的类实例都将具有以下线程亲和性新线程:-
QObject* pObject = new QObject;
pObject->moveToThread(pThread);
不过,pThread 的线程亲和性是 main 线程,而 pObject 的线程亲和性是新线程;请记住,pThread 实际上是一个线程控制器!
将 pObject 的父级设置为 pThread 是错误的,因为它们具有不同的线程亲和性。这是很多人在尝试从 QThread 继承时遇到的问题,而不是将其用作单独的实体并将 QObjects 移至其中。通常发生的情况是,对象有时是在其继承的 QThread 类的构造函数中创建的,而没有为它们提供父级,也没有意识到这些对象将具有主线程的线程亲和性,而不是他们期望的新线程。
将 QObject 移动到另一个线程也会移动其子级,因此尝试将父级设置为线程(线程控制器!)是没有意义的。
总而言之,您不能将工作对象的父对象设置为 TelnetConnectionThread,因为它们在不同的线程上运行。
但是,如果您尝试在完成后自行清理线程,您可以这样做:-
connect(TelnetConnectionThread, SIGNAL(finished()), TelnetConnectionThread, SLOT(deleteLater()));
【讨论】:
啊!我想我明白了。现在,我希望在我的 pThread 被删除时自动删除 QObject。这可能吗(我猜不是通过 setparent)......还是我必须设置另一个与工作人员删除器相关的信号? 在您的示例代码中,您已经将线程的完成信号连接到工作人员的 deleteLater 插槽,它将按照您的要求进行操作。 对不起 - 我的意思是 QThread 对象,所以我必须设置另一个信号。 查看答案底部的连接语句,这不是您要的吗?以上是关于Qt/C++ 将 worker 的父级更改为 qthread 失败的主要内容,如果未能解决你的问题,请参考以下文章