Errors facing while running QWebSocket in different thread than the main thread.



  • All I want to do is create a websocket client connection using Qt on a thread. Create a processing thread,so that when data comes to the websocket handler, the data is passed(through slots and signals) to the processor ->then the processor processes the data and passes it to the main-thread(again via signals and slots) to render the data.I am doing this because I want to keep the main thread ublocked because processing and websocket data would take lot of time.
    First of all,is this the right approach?
    Second:when I try to run QWebsockets on a different thread I am getting the error .

    QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QWebSocket(0x1a493f30), parent's thread is QThread(0x187fc0e8), current thread is QThread(0xe3fe08)
    

    Not sure where to include this

    (Make sure 'QAbstractSocket::SocketState' is registered using qRegisterMetaType().)
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
     
        QUrl url("ws://localhost:8080");
        websocketObj=new websocketclientimpl(url);
        websocketObj->moveToThread(&workerThread_websocket);
        connect(&workerThread_websocket, &QThread::started, websocketObj, &websocketclientimpl::startConnection);
        workerThread_websocket.start();
        QMainWindow::showMaximized();
     
    }
     
    MainWindow::~MainWindow()
    {
        delete ui;
        workerThread_websocket.quit();
        workerThread_websocket.wait();
    }
    
    using namespace std;
    namespace Ui {
    class MainWindow;
    }
     
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
     
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
     
    private:
        Ui::MainWindow *ui;
        websocketclientimpl *websocketObj;
        calculation *calculationObj;
     
        QThread workerThread_websocket;
        QThread workerThread_calculator;
     
    };
    
    class websocketclientimpl : public QObject
    {
        Q_OBJECT
    public:
        QWebSocket m_webSocket;
        websocketclientimpl(const QUrl &url);
        void startConnection();
        void stopConnection();
     
    private Q_SLOTS:
        void onConnected();
        void onClosed();
        void onTextMessageReceived(QString message);
     
    Q_SIGNALS:
        void processIncomingMessage(QString message);
     
    private:
     
        QUrl m_url;
    };
    
    websocketclientimpl::websocketclientimpl(const QUrl &url){
    this->m_url=url;
    }
     
    void websocketclientimpl::startConnection()
    {
        qDebug() << "WebSocket client:" << m_url;
        connect(&m_webSocket, &QWebSocket::connected, this, &websocketclientimpl::onConnected);
        connect(&m_webSocket, &QWebSocket::disconnected, this, &websocketclientimpl::onClosed);
        QNetworkRequest request=QNetworkRequest(QUrl(m_url));
        m_webSocket.open(request);
     
    }
     
    void websocketclientimpl::stopConnection(){
        m_webSocket.disconnect();
         qDebug() << "WebSocket stopped";
    }
     
    void websocketclientimpl::onConnected()
    {
        qDebug() << "WebSocket connected..";
    }
     
    void websocketclientimpl::onClosed()
    {
     
    }
     
    void websocketclientimpl::onTextMessageReceived(QString message)
    {
        qDebug() << "message received in websocket class"<<message;
        emit processIncomingMessage(message);
    }
    

    Can anyone help me out here? Stuck very badly...



  • The problem is that the m_websocket is allocated during creation of websocketclientimpl.
    At that state websocketclientimpl and m_websocket is in ownership of the mainthread.
    After that you shift websocketclientimpl to workerthread.
    The m_websocket object remains in ownership of mainthread.
    Result: you get the noted error message.

    One possible workaround:
    Use m_webSocket as as QWebsocket pointer.
    Instantiate the m_webSocket in start connection (delete it in stopConnection)

    void websocketclientimpl::startConnection()
    {
        m_webSocket = new QWebSocket;
        qDebug() << "WebSocket client:" << m_url;
        connect(m_webSocket, &QWebSocket::connected, this, &websocketclientimpl::onConnected);
        connect(m_webSocket, &QWebSocket::disconnected, this, &websocketclientimpl::onClosed);
        QNetworkRequest request=QNetworkRequest(QUrl(m_url));
        m_webSocket->open(request);
    
    }
    
    void websocketclientimpl::stopConnection(){
        if (m_webSocket != nullptr) {
        m_webSocket->disconnect();
        qDebug() << "WebSocket stopped";
        m_webSocket->deleteLater();
        }
    }
    

    regards
    Karl-Heinz



  • @karlheinzreichel is correct, just one minor point, you can pass a parent to the constructor of m_webSocket instead of calling deleteLater explicitly as it might even be safer (deleteLater would leak if the event loop in the worker thread is stopped before it gets called)



  • @karlheinzreichel thanks a lot..yes that was the problem and now it is solved..Thanks a ton for pointing it out and for the solution.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.