PDA

View Full Version : On QHTTP::request() method.



zgulser
19th November 2013, 15:57
Hi,

I've just received an old project which some tasks needs to be fullfilled. I know the QHttp class is deprecated and shouldn't be used but I have a time issue that forces me to perform some quicky workarounds on the code without gettings hands dirty in refactoring in order to migrate to QNetworkAccessManager.

I have a question about QHttp class as you might guess. I wonder if do I need to use a seperate thread for network operations performed over QHttp class? As far as I remember, QNetworkAccessManager has it's own internal/seemless worker threads that gets the job done. Is it also similar for example QHttp::request() method as well? I mean do I need to create a worker thread explicitly for a network operation if I use QHttp class?

Regards

ChrisW67
19th November 2013, 20:02
No. No user threads are required for Qt networking (until recently there were no threads used by Qt networking internally either).

zgulser
19th November 2013, 20:13
First of all, thanks for your response.


until recently there were no threads used by Qt networking internally either

How the long time running network operations performed then?

ChrisW67
19th November 2013, 22:18
Asynchronously with signals and slots, exactly as described in the documentation.

zgulser
19th November 2013, 22:49
Pardon me. I understand what you want to point out but it's also stated in the documentation that Http::request() is not a blocking method. Thus, if I call the request from UI thread, it should process the request(QHttp::request()) in a worker thread in order not to block.

The signal-slot mechanism you mentioned should be used to update UI thread from the worker one. Am I wrong?

ChrisW67
20th November 2013, 01:44
Yes, you are wrong. You said it yourself, the request(), get(), post() and head() methods do not block the UI thread. When a request completes, the state changes, or data is available you will see a signal from the QHttp object announcing that.

Here is a complete example showing the UI is responsive during a longer (22MB) download. Try resizing as it runs.:


#include <QApplication>
#include <QVBoxLayout>
#include <QLabel>
#include <QTimer>
#include <QHttp>

class Widget: public QWidget {
Q_OBJECT

QTimer *timer;
QHttp *http;
QLabel *timerLabel;
QLabel *infoLabel;
int tick;
int bytes;

public:
Widget(QWidget *p = 0): QWidget(p) {
timerLabel = new QLabel("", this);
infoLabel = new QLabel("", this);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(timerLabel);
layout->addWidget(infoLabel);

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), SLOT(handleTimer()));
timer->setInterval(1000);
timer->start();

http = new QHttp(this);
connect(http, SIGNAL(requestStarted(int)), SLOT(handleStarted(int)));
connect(http, SIGNAL(readyRead(QHttpResponseHeader)), SLOT(handleRead(QHttpResponseHeader)));
connect(http, SIGNAL(requestFinished(int,bool)), SLOT(handleFinished(int,bool)));

http->setHost("www.nasa.gov");
http->get("/sites/default/files/pia17582.jpg");

tick = 0;
bytes = 0;
}

private slots:
void handleTimer() {
timerLabel->setText(QString::number(tick++));
}
void handleStarted(int id) {
infoLabel->setText(QString("Request %1 started").arg(id));
}
void handleRead(const QHttpResponseHeader &header) {
QByteArray ba = http->readAll();
bytes += ba.size();
infoLabel->setText(QString("Read %1 bytes").arg(bytes));
}
void handleFinished(int id, bool error) {
infoLabel->setText(QString("Request %1 finished").arg(id));
}
};

int main(int argc, char **argv)
{
QApplication app(argc, argv);
Widget w;
w.show();
return app.exec();
}
#include "main.moc"

zgulser
20th November 2013, 08:15
Hi,

I exactly understood what you told about async signal-slot messaging. I'm only saying this messaging should be a type of queued connection since signal receiver is in the UI thread where sender is not.

Thanks for your valuable responses by the way.

anda_skoa
20th November 2013, 10:18
The sender (QHttp) is also in the UI thread.
Even if it were not, Qt::AutoConnection would take care of the thread bridiging.
But, again, this is not the case here since there is only one thread involved.

Cheers,
_