我从 QThread 调用 QTcpSocket 类的写入函数时出现错误

Posted

技术标签:

【中文标题】我从 QThread 调用 QTcpSocket 类的写入函数时出现错误【英文标题】:An error ouucrred while I calling the write function of the QTcpSocket class from a QThread 【发布时间】:2016-07-19 03:39:05 【问题描述】:

我正在学习 Qt 中的多线程编程,然后当我从 QThread 调用 QTcpSocket 类的 write 函数时,函数输出为:

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNativeSocketEngine(0x6f1840), parent's thread is QThread(0x624e90), current thread is QThread(0x716ed0)

我调用 write 函数的代码:

QString Processor::GetSystemInfoOfClient() const

    QString result;
    const char *send_buffer = "GSIOC";
    char receive_buffer[100];
    this->cli_sock->write(send_buffer);
    this->cli_sock->waitForBytesWritten();
    this->cli_sock->waitForReadyRead(100000);
    this->cli_sock->read(receive_buffer, 100);
    result = QString(receive_buffer);
    return result;

我接受连接的代码:

void Processor::Accept()

    this->cli_sock = m_server->nextPendingConnection();
    this->cli_addr = this->cli_sock->peerAddress();
    this->cli_port = this->cli_sock->peerPort();

连接处理器的定义:

class Processor : public QObject

    Q_OBJECT
public:
    explicit Processor(QObject *parent = 0, QTcpServer *server = nullptr);
private:
    QTcpServer *m_server = nullptr;
    QTcpSocket *cli_sock = nullptr;
    QHostAddress cli_addr;
    quint16 cli_port;

    QString GetSystemInfoOfClient() const;
signals:
   void GetDetailedFinished(const QString &address,const QString &port, const QString &SystemInfo);
public slots:
   void GetClientDetail();
   void Accept();
;

然后我将处理器移动到QThread

    Processor *processor = new Processor(0, server);
    processor->moveToThread(&processor_thread);
    connect(&processor_thread, &QThread::finished, processor, &QObject::deleteLater);
    connect(this, &Processor_Controller::Accept, processor, &Processor::Accept);
    connect(this, &Processor_Controller::GetClientDetail, processor, &Processor::GetClientDetail);
    connect(processor, &Processor::GetDetailedFinished, this, &Processor_Controller::PassClientDetail);
    processor_thread.start();

我在主线程中创建了QTcpServer

    // The address of the server
    QHostAddress srv_addr("127.0.0.1");

    // The server listen port
    quint16 srv_port = 9895;

    Processor_Controller *controller = new Processor_Controller(0, &server);

    connect(&server, &QTcpServer::newConnection, controller, &Processor_Controller::BeginProcess);

    connect(controller, &Processor_Controller::DisplayClientDetail, this, &MainWindow::DisplayClientDetail);

    // BeginListen
    if(!server.listen(srv_addr, srv_port))
        emit statusBar()->showMessage("Listen Failed");
    else
        emit statusBar()->showMessage("Listen Success");

调用GetSystemInfoOfClient函数的函数:

void Processor::GetClientDetail()

    QString address    = this->cli_addr.toString();
    QString port       = QString::number(this->cli_port);
    QString SystemInfo = this->GetSystemInfoOfClient();
    emit this->GetDetailedFinished(address, port, SystemInfo);

处理器的构造函数:

Processor::Processor(QObject *parent, QTcpServer *server) : QObject(parent)

    this->m_server = server;

我只想在主线程中创建一个服务器并在处理器类中处理连接。如何在不改变这种想法的情况下避免这个错误?

【问题讨论】:

当您初始化cli_sock 变量时,尝试将封闭的Processor 对象设置为父对象 我已经尝试过这样做,但没有太大区别 更多的想法:1)在堆上创建cli_addr,而不是在堆栈上2)向我们展示Processor构造函数的代码。此错误与线程关联性有关,即您在一个线程中创建了一些 QObject 并在另一个线程中使用 GetSystemInfoOfClient 的电话在哪里? 处理器构造函数只有一行代码: Processor::Processor(QObject *parent, QTcpServer *server) : QObject(parent) this->m_server = server; 【参考方案1】:

我在Processor::Accept函数中使用这两行代码就解决了这个问题

QTcpSocket *m_socket = m_server->nextPendingConnection();
this->cli_sock->setSocketDescriptor(m_socket->socketDescriptor(), m_socket->state(), m_socket->openMode());

【讨论】:

请查看Qt Threaded Fortune Server Example 以及他们实现多线程服务器的方式并遵循他们的模式。 setSocketDescriptor的documentation末尾的注释,不可能用相同的本机套接字描述符初始化两个抽象套接字。。在您的代码中,您在cli_sockm_socket 中使用相同的套接字描述符。你迟早会遇到问题。 . . 我会看到示例,而m_socket 就像一个临时对象一样,我将一无所获。

以上是关于我从 QThread 调用 QTcpSocket 类的写入函数时出现错误的主要内容,如果未能解决你的问题,请参考以下文章

QTcpSocket使用过程中的一些问题记录

如果我从线程调用 QMetaObject::invokeMethod 到单音,调用是不是仍在该 qthread 中?

QTcpSocket Disconnected() 未发出信号

QTcpSocket 或 QSslSocket 会自动创建读/写线程吗?

QT下QThread学习

ffmpeg实时编码解码部分代码