程序打开后,将通过QNetworkAccessManager::connectToHostEncrypted()
的服务器建立连接,该连接在MainWindow
的构造函数中调用。这将冻结GUI线程,并导致明显的延迟,直到连接完成。 (有时要花整整一秒钟的时间)
该问题由于我的程序在启动时淡入而变得更糟,因此,在GUI线程被阻止时,直到连接完成后才开始淡入。在默认的Qt项目中,这可以通过其他方式看到,例如未绘制小部件。
为了保持GUI线程的运行,我将QNetworkAccessManager
移到了一个完全不同的线程中,QThread
认为这可以解决问题,但是GUI线程仍然冻结。这对我来说毫无意义。
这是一个最少可编译的示例项目。
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;
}
这个示例项目创建了Connection
的一个实例,它是QNetworkAccessManager
的子类,然后我通过moveToThread()
移到另一个线程。这就是我所有工作线程的处理方式。
发出线程的start()
信号时,openConnection()
调用GUI线程冻结的地方connectToHostEncrypted()
。
我尝试仅调用常规HTTP请求,但是问题仍然存在,因为仍然需要进行初始连接。
即使连接是在另一个线程中完成的,GUI线程为什么仍然冻结?
答案 0 :(得分:1)
尝试使用:
connect(connectionThread, SIGNAL(started()), connection, SLOT(openConnection(),Qt::QueuedConnection);
答案 1 :(得分:1)
问题是我将this
作为父级传递给Connection
实例,这意味着moveToThread()
无法完成。我只需要检查输出日志就可以看到它,但是我一定错过了!
通过删除该父对象,该连接现在位于其自己的线程中。
我通过在QThread::sleep(3)
调用中调用openConnection()
进一步测试了这一点,仍然没有延迟。