c++ - QNetworkAccessManager 即使在另一个线程中也会卡住 GUI

标签 c++ qt qthread qnetworkaccessmanager

当我的程序打开时,通过 QNetworkAccessManager::connectToHostEncrypted() 与我的服务器建立连接,该连接在 MainWindow 的构造函数中调用。这会卡住 GUI 线程并导致明显的延迟,直到连接完成。 (有时超过整整一秒)

这个问题由于我的程序在启动时淡入而变得更糟,因此当 GUI 线程被阻塞时,淡入直到连接完成后才开始。在默认的 Qt 项目中,这在其他方面很明显,例如未绘制小部件。

为了让 GUI 线程继续运行,我将 QNetworkAccessManager 移动到一个完全不同的线程中,使用 QThread 认为这可以解决问题,但 GUI 线程仍然卡住。这对我来说毫无意义。

这是一个最小可编译的示例项目。

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QThread>

class Connection : public QNetworkAccessManager
{
    Q_OBJECT
public:
    Connection(QObject *parent) : QNetworkAccessManager(parent){}

public slots:
    void openConnection(){
        connectToHostEncrypted("https://www.url.com");
    }

signals:
    void closeThread(bool);
};


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    QThread *connectionThread;
    Connection *connection;
};

#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    connection = new Connection(this);

    connectionThread = new QThread();
    connection->moveToThread(connectionThread);
    connect(connectionThread, SIGNAL(started()), connection, SLOT(openConnection()));
    connect(connection, SIGNAL(closeThread(bool)), connectionThread, SLOT(quit()));
    connect(connectionThread, SIGNAL(finished()), connectionThread, SLOT(deleteLater()));

    connectionThread->start();
}

MainWindow::~MainWindow()
{
    delete connection;
    delete ui;
}

这个示例项目创建了 Connection 的实例,它是 QNetworkAccessManager 的子类,然后我通过 moveToThread() 将其移动到另一个线程。这就是我处理所有工作线程的方式。

当线程的 start() 信号发出时,openConnection() 调用 connectToHostEncrypted(),这就是 GUI 线程卡住的地方。

我试过只调用常规 HTTP 请求,但是问题仍然存在,因为仍然需要建立初始连接。

为什么即使在另一个线程中完成连接,GUI 线程仍然卡住?

最佳答案

问题是我将 this 作为父级传递给 Connection 实例,这意味着 moveToThread() 无法完成。我只需要检查输出日志就可以看到,但我一定是错过了!

通过删除该父级,连接现在位于它自己的线程中。

我通过在 openConnection() 调用中调用 QThread::sleep(3) 进一步测试了这一点,仍然没有延迟。

关于c++ - QNetworkAccessManager 即使在另一个线程中也会卡住 GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56470208/

相关文章:

c++ - 在 OpenCV 中加快将图像写入硬盘的速度

multithreading - 循环时更新PyQt4 GUI

java - 如何为 C++ 项目开发 API

c++ - Qt 中的 Internet Explorer 窗口?

c++ - 如何迭代QAbstractListModel?

c++ - 在 QListWidget 中使用图像,这可能吗?

c++ - BlockingQueue 的 QWaitCondition : Destroyed while threads are still waiting

C++ 枚举 [字符串] 错误

c++ - 运行 boost::asio 套接字示例时我传递给客户端的参数是什么

c# - 从 C# 迁移到 C++(加上在同一解决方案中使用两者)