如何在线程中关闭 QWebSocket?

Posted

技术标签:

【中文标题】如何在线程中关闭 QWebSocket?【英文标题】:How to close QWebSocket in thread? 【发布时间】:2019-03-05 07:32:40 【问题描述】:

我将一个 QWebSocket 移动到一个线程,然后如何在主线程中关闭它?

由于我将其移至工作线程,因此我无法直接从主线程调用 close。它会因这条消息而崩溃

QSocketNotifier:不能从另一个线程启用或禁用套接字通知器

没有线程,它工作正常。

这是我的代码。 有任何想法吗?非常感谢!

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QWebSocket>
#include <QThread>

namespace Ui 
class MainWindow;


class MainWindow : public QMainWindow

        Q_OBJECT

    public:
        explicit MainWindow(QWidget *parent = nullptr);
        ~MainWindow();

    private slots:
        void on_connectButton_clicked();
        void on_disconnectButton_clicked();

        void onClientConnected();
        void onClientClosed();
        void onClientTextMsg(const QString &msg);

    private:
        Ui::MainWindow *ui;
        QWebSocket *mClient;
        QThread mWorkerThread;
;

#endif // MAINWINDOW_H
#include "MainWindow.h"
#include "ui_MainWindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    mClient(nullptr)

    ui->setupUi(this);

    mWorkerThread.start();

    qRegisterMetaType<QAbstractSocket::SocketState>();


MainWindow::~MainWindow()

    delete ui;


void MainWindow::on_connectButton_clicked()

    mClient = new QWebSocket();
    connect(mClient, &QWebSocket::connected, this, &MainWindow::onClientConnected, Qt::DirectConnection);
    connect(mClient, &QWebSocket::disconnected, this, &MainWindow::onClientClosed, Qt::DirectConnection);
    connect(mClient, &QWebSocket::textMessageReceived, this, &MainWindow::onClientTextMsg, Qt::DirectConnection);
    mClient->open(QUrl("ws://192.168.2.2:1936"));
    mClient->moveToThread(&mWorkerThread);


void MainWindow::on_disconnectButton_clicked()

    // FIXME crash
    // QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
    mClient->close();


void MainWindow::onClientConnected() 
    qDebug() << "ws client connected";


void MainWindow::onClientClosed() 
    qDebug() << "ws client closed, " << mClient->closeReason() << mClient->errorString();


void MainWindow::onClientTextMsg(const QString &msg) 
    qDebug() << "ws recv msg:" << msg;

【问题讨论】:

【参考方案1】:

使用QMetaObject::invokeMethod:

QMetaObject::invokeMethod(mClient, "close", Qt::QueuedConnection);

【讨论】:

谢谢,它有效。但是我发现了一个新问题。在高延迟网络环境中,客户端似乎阻塞了工作线程中的事件循环,也许? close 方法不会调用 util all 收到的 msg。如何立即关闭客户端? 终于在QT源代码qwebsocketframe.pp中找到了anwser。也许我应该更改此代码... ``` //TODO: waitForReadyRead 真的应该更改 //现在,当在 GUI 线程中使用 WebSocket 时 //GUI 最多会挂起 5 秒 //也许,一个如果 (!pIoDevice->waitForReadyRead(5000)) ``` 应该使用 QStateMachine

以上是关于如何在线程中关闭 QWebSocket?的主要内容,如果未能解决你的问题,请参考以下文章

如何让线程等待 JFrame 在 Java 中关闭?

如何从 ViewModel 命令生成的线程中关闭窗口? [复制]

如何在另一个线程中关闭 MFC 模态对话框并获得对话框返回值?

如何在 VS 2013 中关闭 Razor 突出显示?

如何在 Rust 中关闭 Unix 套接字?

linux环境中关闭tomcat,通过shutdown.sh无法彻底关闭--线程池