无法使用QtNetwork,因为应用程序使用不同的线程

时间:2016-03-31 10:07:28

标签: c++ qt qthread qobject qtnetwork

当我使用QtNetwork时,我的应用程序出现了一个奇怪的行为。我可以轻松地创建QTcpSeverQTcpSocket实例,一切运行正常,但当涉及到QTcpSocket::write()时,会发生以下错误:

错误

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNativeSocketEngine(0x7f66980022e0), parent's thread is QThread(0x7f66a0020be0), current thread is QThread(0x7f66a0020e20)
QSocketNotifier: Can only be used with threads started with QThread

对我来说有什么奇怪的:我不知道这个QThread(0x7f66a0020e20)是什么/在哪里以及如何影响它(看看调试下面)

该计划

我通过网络支持扩展我的主应用程序(这是一个库)。我把网络服务放到了一个额外的课程中。

这里是创建我的网络支持的主应用程序/库的摘录:

QThread *thread = new QThread;
wifi = new WirelessNet(0, thread);
wifi->moveToThread(thread);
connect(thread,SIGNAL(started()), wifi,SLOT(initWifi()));
thread->start();

网络类扩展名:

WirelessNet::WirelessNet(QObject *parent, QThread *comThread): QTcpServer(parent)
{
     clientThread = comThread;
}

void WirelessNet::initWifi()
{
    listen(QHostAddress::Any, 5220);
    connect(this,SIGNAL(newConnection()),this,SLOT(connectionRequest()));
}

void WirelessNet::connectionRequest()
{
    client = this->nextPendingConnection();
    if(client)
        connect(client, SIGNAL(readyRead()), this, SLOT(receiveMessage()));
}

void WirelessNet:sendData(QByteArray msg)
{
if (client)
{
    qDebug()<<"FIRST "<< client->thread() << " - " << this->thread() << "\n";
    client->write(msg);
    client->waitForBytesWritten();
    qDebug()<<"LAST " << client->thread() << " - " << this->thread() << "\n";
}
}

(client和clientThread是类成员:分别是QTcpSocket *,QThread *)

调试

以下是控制台在sendData()部分打印出来的内容:

FIRST QThread(0x7f66a0020be0) - QThread(0x7f66a0020be0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNativeSocketEngine(0x7f66980022e0), parent's thread is QThread(0x7f66a0020be0), current thread is QThread(0x7f66a0020e20)
QSocketNotifier: Can only be used with threads started with QThread
LAST QThread(0x7f66a0020be0) - QThread(0x7f66a0020be0)

结论

换句话说,我不知道应该在哪个对象上应用moveToThread()。我已经尝试了client->moveToThread(clientThread)以及this->moveToThread(clientThread)。不幸的是,我没有看到任何其他要检查的对象。

有人有想法吗?

2 个答案:

答案 0 :(得分:3)

您似乎直接从主线程调用client。这会导致该函数内的所有内容也在主线程中运行。您的client位于新线程中,并且不是线程安全的。它尝试创建子节点,但当前线程与WirelessNet:sendData所在的线程不同。这就是您收到该错误消息的原因。

您只需将&作为一个插槽并通过主线程中的信号调用它即可解决此问题。

答案 1 :(得分:1)

我的猜测是你的类的构造函数在调用线程中被调用,而线程本身在你的类的run()方法中运行。解决方案是在QTcpServer方法的开头初始化run(),以便通过该类进行初始化和通信在同一个线程中完成。