如何在线程中关闭 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?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 ViewModel 命令生成的线程中关闭窗口? [复制]