Solved 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 callingdeleteLater
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.