QtQNetworkAccessManager post方法仅在主线程中工作

Qt QNetworkAccessManager post method works only in main thread

本文关键字:线程 工作 post 方法 QtQNetworkAccessManager      更新时间:2024-09-29

我的Qt QNetworkAccessManager有问题。我想用它与我的web服务器交互,后者提出了一个POST api。

在我的主函数中,我可以使用QNetworkAccessManager::post((。我的服务器从客户端接收数据。但是,如果我在另一个线程中移动post函数,我的服务器就会收到任何东西。

下面是我的代码示例:

工作代码:

#include <iostream>
#include <QNetworkRequest>
#include <QUrl>
#include <QNetworkAccessManager>
#include <QCoreApplication>
#include <thread>
#include <QThread>
#include <QObject>
#include <QNetworkReply>
class PostClass: public QObject {
Q_OBJECT
public:
PostClass() {
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onfinish(QNetworkReply*)));
};
QNetworkAccessManager* manager = nullptr;
public slots:
void post() {
const QUrl url("http://[ip:port]/users");
QNetworkRequest req(url);
manager->get(req);
QNetworkRequest req1(QUrl("[ip:port]/event"));
req1.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
qDebug() << "Send new request";
QByteArray data(R"({"data": "QtGroupHEllo"})");
manager->post(req1, data);
};
void onfinish(QNetworkReply* rep) {
qDebug() << "reply delete!";
rep->deleteLater();
qDebug() << "https post_request done!";
};
};
class ThreadTmp: public QThread {
Q_OBJECT
public:
ThreadTmp() = default;
public slots:
void onfinish(QNetworkReply* rep) {
rep->deleteLater();
qDebug() << "reply delete!";
qDebug() << "https post_request done!";
};
signals:
void postRequest();
protected:
void run() override {
while (1) {
emit postRequest();
sleep(1);
}
}
};

int main(int argc, char* argv[]) {
QCoreApplication app (argc, argv);
std::cout << "Hello, World!" << std::endl;
PostClass postObj;
ThreadTmp tmp();
QObject::connect(&tmp, SIGNAL(postRequest()), &postObj, SLOT(post()));
tmp.start();
return app.exec();
}
#include "main.moc"

但是,如果我在ThreadTmp类中移动PostClass实例,在run函数中,只有get工作,post不工作,因为在我的服务器中,我只收到get请求,而没有收到post请求:

#include <iostream>
#include <QNetworkRequest>
#include <QUrl>
#include <QNetworkAccessManager>
#include <QCoreApplication>
#include <thread>
#include <QThread>
#include <QObject>
#include <QNetworkReply>
class PostClass: public QObject {
Q_OBJECT
public:
PostClass() {
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onfinish(QNetworkReply*)));
// connect(manager, SIGNAL(finished(QNetworkReply*)), manager, SLOT(deleteLater()));
};
QNetworkAccessManager* manager = nullptr;
public slots:
void post() {
const QUrl url("http://[ip:port]/users");
QNetworkRequest req(url);
manager->get(req);
QNetworkRequest req1(QUrl("http://[ip:port]/event"));
req1.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
qDebug() << "Send new request";
QByteArray data(R"({"data": "QtGroupHEllo"})");
manager->post(req1, data);
};
void onfinish(QNetworkReply* rep) {
qDebug() << "reply delete!";
rep->deleteLater();
qDebug() << "https post_request done!";
};
};
class ThreadTmp: public QThread {
Q_OBJECT
public:
ThreadTmp() = default;
public slots:
void onfinish(QNetworkReply* rep) {
rep->deleteLater();
qDebug() << "reply delete!";
qDebug() << "https post_request done!";
};
signals:
void postRequest();
protected:
void run() override {
PostClass postObj;
connect(this, SIGNAL(postRequest()), &postObj, SLOT(post()));
while (1) {
emit postRequest();
sleep(1);
}
}
};

int main(int argc, char* argv[]) {
QCoreApplication app (argc, argv);
std::cout << "Hello, World!" << std::endl;
ThreadTmp tmp();
tmp.start();
return app.exec();
}
#include "main.moc"

我不知道我为什么会有这种行为。。。

为了在线程中有一个事件循环,您需要使用一个阻塞.exec()。只要重写run(),就会导致线程触发该代码,然后终止。当您通过QNetworkAccessManager发布时,这实际上是在后台异步发生的,由开箱即用的QEventLoop驱动。如果您正在与一个简单的RESTapi交互,或者使用get((下载一个大文件,那么通常不需要使用另一个线程。Qt为您处理您可能试图通过另一个线程避免的问题,即堵塞主线程并通过网络流量阻碍性能。使用另一个线程的最佳原因是在需要很长时间的情况下处理服务器的响应。要做到这一点,只需跨线程挂接信号/插槽,同时将后操作/网络管理器留在主线程中。(当然,一般来说…(