Unsolved QNetworkAccessManager finished signal emitted to late
-
I am trying to save a reply in other object which doesn't have anything to do with the downloader class but the finished signal is emitted at the end of the program so I am passing an empty string to the other object. Any ideas how to make
response = m_response;
work?#include "downloader.h" Downloader::Downloader(QObject *parent) : QObject(parent) { } void Downloader::doDownload(QUrl &url, QString &response) { p_manager = new QNetworkAccessManager(this); connect(p_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*))); p_manager->get(QNetworkRequest(url)); response = m_response; } void Downloader::replyFinished (QNetworkReply *reply) { if(reply->error()) { m_response = reply->errorString(); } else { qDebug() << reply->header(QNetworkRequest::ContentTypeHeader).toString(); qDebug() << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toString();; qDebug() << reply->header(QNetworkRequest::ContentLengthHeader).toULongLong(); qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); m_response = reply->readAll(); } reply->deleteLater(); }
-
@Radu.Amh said in QNetworkAccessManager finished signal emitted to late:
response = m_response;
What is
response
andm_response
? You do not set either of them to any value in doDownload(). -
in void Downloader::replyFinished (QNetworkReply *reply) you can find m_response = reply->errorString();
response is what i want to pass to the other object -
Hi
Why not hook up the other class to finished signal too ?
I assume there cant be any response to copy before finished has been seen.Also you sentence.
- the finished signal is emitted at the end of the program
sounds a bit odd. does it means it takes LONG time to download or
WHY first in the end of the program ?
- the finished signal is emitted at the end of the program
-
@Radu.Amh said in QNetworkAccessManager finished signal emitted to late:
response is what i want to pass to the other object
Connect that object to finished() signal, then.
Or set the response in the replyFinished() method. Doing it in doDownload() is way too soon.
-
@Radu.Amh said in QNetworkAccessManager finished signal emitted to late:
void Downloader::doDownload(QUrl &url, QString &response) { p_manager = new QNetworkAccessManager(this); connect(p_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*))); p_manager->get(QNetworkRequest(url)); response = m_response; }
hi
p_manager->get
is not a synchronus function, thereforem_response
in the next line will always be an empty string!only after the
replyFinished
signal is fired, is m_response not empty anymore and you can pass it along.also your
p_manager
leaks memory! -
Well, this is what I am trying to do:
class WebPage
{
private:
QUrl m_url;
QString m_name;
QString m_location;
QString m_response;
QFile p_file;public:
WebPage(const QString &url, const QString &name, const QString &location);
WebPage(const WebPage &)=delete;
void download(Downloader &down);};
void WebPage::download(Downloader &down)
{
down.doDownload(m_url, m_response);
if(p_file.open(QIODevice::ReadWrite))
{
QTextStream stream( &p_file );
stream << m_response;
p_file.flush();
p_file.close();
}
}downloading a webpage but also being able to download another webpage later in the same program.
-
@J.Hilk I understood get is not a synchronous function but I need the reply for the other object, webpage, so how do I make it to deliver it in time?
@sierdzio how do I connect the object to the finished() signal?
@mrjj why at the end, I've watched it with the debugger and void Downloader::replyFinished (QNetworkReply *reply) is the last function called, after that deconstructors are called -
@Radu.Amh
we would have to see a good part more of your implementation.however, this quick and dirty solution should also work. But I recommend rethinking your approach:
void Downloader::doDownload(QUrl url, QString &response) { QNetworkAccessManager *manager = new QNetworkAccessManager(); QString str; QNetworkReply *reply = manager->get(QNetworkRequest(url)); connect(reply, &QNetworkReply::finished, this, [reply, &str]{ str = reply->readAll(); reply->deleteLater(); }); QEventLoop loop; connect(manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit); loop.exec(); manager->deleteLater(); response = str; }
-
@J.Hilk Actually it is something I had in mind but I didn't know about QEventLoop. Thank you! Until a better solution comes this is the best.
-
@Radu.Amh
It is a Bad solution
It forces synchronus behaviour on an asynchronus methodBetter would be a Signal from your download Class that sends the recieved Data to a Slot in your other class
Signals can have arguments, for example a String, to send Data across