【发布时间】:2023-04-06 11:44:01
【问题描述】:
当我的程序打开时,通过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 线程仍然冻结?
【问题讨论】:
标签: c++ qt qthread qnetworkaccessmanager