简体   繁体   English

QNetworkAccessManager即使在另一个线程中也会冻结GUI

[英]QNetworkAccessManager freezes GUI even when in another thread

When my program opens, a connection is made to my server via QNetworkAccessManager::connectToHostEncrypted() which is called in the constructor of MainWindow . 当我的程序打开时,通过QNetworkAccessManager::connectToHostEncrypted()与我的服务器建立连接,该连接在MainWindow的构造函数中调用。 This freezes the GUI thread and causes a noticeable delay until the connection is finished. 这将冻结GUI线程,并导致明显的延迟,直到连接完成。 (Sometimes over a full second longer) (有时超过一整秒钟)

This problem is worsened by the fact that my program fades in at startup, so while the GUI thread is blocked, the fade in doesn't start until after the connection is done. 由于我的程序在启动时会逐渐淡入,因此使该问题更加严重,因此,在GUI线程被阻止的情况下,直到连接完成后才会开始淡入。 In a default Qt project, this is noticeable in other ways like widgets not being painted. 在默认的Qt项目中,这可以通过其他方式看到,例如未绘制小部件。

To keep the GUI thread going, I moved QNetworkAccessManager into a completely different thread with QThread thinking this would solve the issue, however the GUI thread still freezes. 为了使GUI线程继续运行,我将QNetworkAccessManager移到了一个完全不同的线程中, QThread认为这可以解决问题,但是GUI线程仍然冻结。 This makes no sense to me. 这对我来说毫无意义。

Here is a minimally compilable example project. 这是一个最小编译的示例项目。

mainwindow.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

mainwindow.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;
}

This example project creates an instance of Connection which is a subclass of QNetworkAccessManager that I then move to another thread via moveToThread() . 这个示例项目创建一个Connection实例,它是QNetworkAccessManager的子类,然后我通过moveToThread()移到另一个线程。 This is how I do all my worker threads. 这就是我处理所有工作线程的方式。

When the thread's start() signal is emitted, openConnection() calls connectToHostEncrypted() which is where the GUI thread freezes. 发出线程的start()信号时, openConnection()调用GUI线程冻结的connectToHostEncrypted()

I have tried just calling a regular HTTP request instead, however the problem persists since an initial connection still needs to be made. 我尝试仅调用常规HTTP请求,但是问题仍然存在,因为仍需要进行初始连接。

How come the GUI thread still freezes even though the connection is done in another thread? 即使连接是在另一个线程中完成的,GUI线程怎么仍然冻结?

尝试使用:

connect(connectionThread, SIGNAL(started()), connection, SLOT(openConnection(),Qt::QueuedConnection);

The issue was I passed this as a parent to the Connection instance which meant moveToThread() couldn't be completed. 问题是我将this作为父级传递给Connection实例,这意味着无法完成moveToThread() I just had to check the output log to see that, but I must have missed it! 我只需要检查输出日志就可以看到它,但是我一定错过了!

By removing that parent, the connection was now in it's own thread. 通过删除该父对象,该连接现在位于其自己的线程中。

I further tested this by calling QThread::sleep(3) inside that openConnection() call and there was still no delay. 我通过在openConnection()调用内调用QThread::sleep(3)进行了进一步测试,但仍然没有延迟。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM