Russian Qt Forum

Qt => Работа с сетью => Тема начата: neosapient1 от Январь 29, 2020, 19:58



Название: Можно ли делать QWebSocket в дочернем потоке?
Отправлено: neosapient1 от Январь 29, 2020, 19:58
Здравствуйте.

Пишу приложение GUI + QWebSocket. Программа принимает большой объем данных по QWebSocket, и видно как GUI тормозит.
Чтобы интерфейс пользователя не тормозил, хочу вынести GUI в дочерний поток.

В общем, написал тестовый класс Thread.
В процессе тестов выяснил, что объект QWebSocket должен создаваться в самом дочернем потоке.
В программе не работает webSocket->close(). Программа выкидывает ошибку. Как исправить?

thread.h
Код:
#ifndef THREAD_H
#define THREAD_H

#include <QObject>
#include <QThread>
#include <QtWebSockets/QWebSocket>

class Thread: public QThread
{
    Q_OBJECT
public:
    Thread();
    void run();
Q_SIGNALS:
    void closed();

private Q_SLOTS:
    void onConnected();
    void onRead(QString message);
    void onClosed();

public:
    QWebSocket *p_webSocket;
};

#endif // THREAD_H

thread.cpp
Код:
#include "thread.h"

Thread::Thread()
    : p_webSocket(NULL)
{}

void Thread::run()
{
    while(true){
        QWebSocket webSocket;  // <-- создаю объект тут
        p_webSocket = &webSocket;
        connect(p_webSocket, &QWebSocket::connected, this, &Thread::onConnected);
        connect(p_webSocket, &QWebSocket::disconnected, this, &Thread::onClosed);
        p_webSocket->open(QUrl("wss://echo.websocket.org/"));
        exec();
    }
}

void Thread::onConnected()
{
    qDebug() << "WebSocket connected";
    connect(p_webSocket, &QWebSocket::textMessageReceived,
            this, &Thread::onRead);
    p_webSocket->sendTextMessage(QStringLiteral("test"));
}

void Thread::onRead(QString message)
{
    qDebug() << "Message received:" << message;
    disconnect(p_webSocket, &QWebSocket::textMessageReceived,
            this, &Thread::onRead);
    p_webSocket->close();      // <--- тут происходит ошибка
}

void Thread::onClosed()
{
    qDebug() << "onClosed";
}

main.cpp
Код:
#include <QCoreApplication>
#include "thread.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Thread thread;
    thread.start();
    return a.exec();
}

Ошибка
Цитировать
QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
QObject::connect: Cannot queue arguments of type 'QAbstractSocket::SocketState'
(Make sure 'QAbstractSocket::SocketState' is registered using qRegisterMetaType().)
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 2dd1c48. Receiver '' (of type 'QNativeSocketEngine') was created in thread 9bfed4", file kernel\qcoreapplication.cpp,line 568

Спасибо.


Название: Re: Можно ли делать QWebSocket в дочернем потоке?
Отправлено: qate от Январь 30, 2020, 09:40
"Правильная работа с потоками в Qt" https://habr.com/ru/post/467261/
Лучше покажи минимальный пример, где QWebSocket тормозит, возможно там уже все не так.