无法为不同线程中的父级创建子级
Posted
技术标签:
【中文标题】无法为不同线程中的父级创建子级【英文标题】:Cannot create children for a parent that is in a different thread 【发布时间】:2012-05-03 11:27:48 【问题描述】:我在 MyThread.cpp 和 .h 中定义了一个 QThread。我有一个私有的 QTcpSocket。
class MyThread: public QThread
Q_OBJECT
public:
MyThread();
virtual ~MyThread();
public slots:
void reconnect();
signals:
protected:
void run(void);
private:
QTcpSocket *socket;
;
void MyThread::run(void)
bool connected = false;
connected = prepareSocket(QString::fromLatin1((Global::directionIPSerialServer).toLocal8Bit().data()), 8008, socket);
另一方面,我在 Functions.cpp 和 .h 中定义了一组函数,它们没有定义在 Functions 类中,而是定义在命名空间中。
bool Functions::prepareSocket(QString address, int port, QTcpSocket *socket)
socket->connectToHost(address, port);
if(!socket->waitForConnected(Global::maxTimueToConnectByTCP))
qDebug()<<"Error: "<<socket->errorString();
return false;
return true;
然后,如果我错了,请纠正我,当我将函数调用到 Functions 以将 MyThread 的 QTcpSocket 连接到主机时,我假设我在同一个线程上,因为我是从线程调用函数我创造了一个,而不是一个不同的。
尽管如此,在 socket->connectToHost 上我得到 QObject: Cannot create children for an parent that is in a different thread. 两次。
这是为什么呢?怎么了?
【问题讨论】:
你在哪里创建套接字? 【参考方案1】:尝试:QObject::moveToThread。这应该可以解决问题。
【讨论】:
好的,成功了。我已经阅读过这种方法,但我认为它是出于不同的目的。如果您在创建后不调用 moveToThread(this),我不明白为什么创建到 QThread 中的 QTcpSocket 不会附加到该线程。为什么会出现这种行为? 因为您的新线程中需要一个事件循环。见这篇文章:doc.qt.nokia.com/4.7-snapshot/thread-basics.html moveToThread(this) 总是错误的并且不安全。您可以“推送”其他线程的对象,而不是拉取它们。 没错,这不是好方法而是简单的方法。您不应该从 qthread 派生。但是如果你确实 movetothread 是让 qobject 工作的唯一方法 muma:不应该有“但如果你这样做了”。从概念上讲,QThread不是一个线程本身,而是一个线程控制器。线程控制器住在它控制的线程中是没有意义的。您需要一个控制器在线程终止后保持活动状态,例如向您发出线程确实终止的信号。【参考方案2】:你不应该从 QThread 派生。在从 QObject 派生的类上实现所有内容。然后,您可以选择在该 QObject 上调用 moveToThread()
以将其移动到新线程。不过,您会发现通常不需要将其移至新线程无论如何,因为现在您将拥有不会停止 GUI 线程的异步、非阻塞代码。
他们这样做的关键是永远不要使用waitxxx
调用。每当您想等待某事时,您会发现当该事发生(或失败)时会发出一个信号。将 slot 连接到该信号。您可能需要多次执行此操作——不同信号的不同插槽。这就是您正确编写异步事件驱动应用程序的方法。
只有在不存在其他 API 时才使用阻塞调用。数据库驱动程序和名称解析器在这方面是出了名的糟糕,但它们是唯一的反例。我说,让他们孤独地死去吧。
【讨论】:
以上是关于无法为不同线程中的父级创建子级的主要内容,如果未能解决你的问题,请参考以下文章
(QNativeSocketEngine)QObject:无法为不同线程中的父级创建子级