2016-07-19 2 views
0

Я узнаю о многопоточном программировании в Qt, а затем, когда я вызываю функцию записи класса QTcpSocket из QThread. Функция выход:Ошибка при вызове функции записи класса QTcpSocket из QThread

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) 

код, который я назвал функцией записи:

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; 
} 

Я просто хочу создать сервер в основном потоке и обработку соединений в классе Процессор. Как я могу избежать этой ошибки без изменения этого мышления?

+0

при инициализации 'cli_sock' переменного попытаться установить ограждающий объект' Processor', как это родительский –

+0

я хава пытался сделать это, но это не имело большого значения. – FancyBirds

+0

больше идей для игры: 1) Создайте 'cli_addr' в куче, а не в стеке 2) Покажите нам код для конструктора' Processor'. Эта ошибка связана с сходством потоков, т. Е. Вы создаете некоторый 'QObject' в одном потоке и используете в другом –

ответ

1

Я решить эту проблему только с помощью этих двух линии кодов в Processor::Accept функции

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

кажется подозрительным , но спасибо за обмен –

+0

, пожалуйста, взгляните на [Qt Threaded Fortune Server Example] (http://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html) и то, как они реализуют многопоточную сервера и следовать их шаблону. – Mike

+0

см. Примечание в конце документации [setSocketDescriptor] (http://doc.qt.io/qt-5/qabstractsocket.html#setSocketDescriptor), * Невозможно инициализировать два абстрактных сокета с помощью такой же собственный дескриптор сокета. *. В вашем коде вы используете один и тот же дескриптор сокета в 'cli_sock' и' m_socket'. у вас скоро будут проблемы. , , – Mike

Смежные вопросы