Qt request never trigger the finished() signal
-
i have something realy strange i have this code :
@m_url.setUrl("www.cnn.com");
QNetworkRequest request;
request.setRawHeader("User-Agent", USER_AGENT.toUtf8());
request.setRawHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,;q=0.7");
request.setRawHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,/*;q=0.8");
request.setRawHeader("Accept-Language", "en-us,en;q=0.5");
request.setRawHeader("Connection", "Keep-Alive");
request.setUrl(m_url);reply = qnam.get(request); //QNetworkAccessManager qnam member of the class; connect(reply, SIGNAL(finished()), this, SLOT(httpFinished()));@
the httpFinished() function that is under private slots: never triggered , why ?
-
Does it work with another url and where you do not specify so many raw header fields?
Also you can try to listen to the error signals as well to make sure nothing weird happens.Like Qt's own example:
@QNetworkRequest request;
request.setUrl(QUrl("http://qt.nokia.com"));
request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");QNetworkReply *reply = manager->get(request);
connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(slotSslErrors(QList<QSslError>)));
@ -
just to be sure , this code is executed in separate thread not in the GUI main thread
i fixed my code still nothing
@ m_url.setUrl("http://qt.nokia.com");
QNetworkRequest request;request.setUrl(m_url);
reply = m_networkManager->get(request);
bool bb = reply->isFinished();connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError(QNetworkReply::NetworkError)));connect(reply,SIGNAL(finished()),
this, SLOT(httpFinished()));connect(reply, SIGNAL(readyRead()), this, SLOT(httpReadyRead())); connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDataReadProgress(qint64,qint64)));
added this :
void HttpClient::slotError(QNetworkReply::NetworkError networkError)
{
if(networkError != QNetworkReply::NoError)
{
QString err = reply->errorString();
LOG_MSG("HttpClient::HandleNetworkError:"+err.toStdString());
}
}
@UPDATE :
i think i know what is wrong but i dont know how to fix it .
this is what i have :
when i put break point in int test = 0;
it getting there before it gets to httpFinished() slot in the HttpClient , mybe this is the problem ?
in the main.cpp@while (i.hasNext())
{
i.next();ThreadWorker* pThreadWorker = new ThreadWorker();
pThreadWorker->setUrl(sUrl);
QThreadPool::globalInstance()->start(pThreadWorker);
}
QThreadPool::globalInstance()->waitForDone();
void ThreadWorker::run()
{
startWork();
}void ThreadWorker::startWork()
{
m_pHttpClient = new HttpClient();
m_pHttpClient->startRequest(m_url);
int test = 0;}
--------------------------------- HttpClient based on the http example from Qt -----------------------------------
HttpClient::HttpClient()
{
m_networkManager = new QNetworkAccessManager(this);
connect(m_networkManager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
this, SLOT(slotAuthenticationRequired(QNetworkReply*,QAuthenticator*)));#ifndef QT_NO_OPENSSL
connect(m_networkManager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
this, SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
#endif
}void HttpClient::startRequest(QUrl url)
{
m_url.setUrl("http://qt.nokia.com/");
QNetworkRequest request;
request.setUrl(m_url);reply = m_networkManager->get(request);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError(QNetworkReply::NetworkError)));connect(reply,SIGNAL(finished()),
this, SLOT(httpFinished()));connect(reply, SIGNAL(readyRead()), this, SLOT(httpReadyRead())); connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDataReadProgress(qint64,qint64)));
}@
-
I just tried the code in a single threaded application and it works just fine for me. I used this code:
In header:
@
private slots:
void slotError(QNetworkReply::NetworkError networkError);
void slotFinished();
private:
QUrl m_url;
QNetworkAccessManager* m_networkManager;
@And in cpp:
@ m_networkManager = new QNetworkAccessManager(this);
m_url.setUrl("http://qt.nokia.com");
QNetworkRequest request;request.setUrl(m_url); QNetworkReply* reply = m_networkManager->get(request); bool bb = reply->isFinished(); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); connect(reply,SIGNAL(finished()), this, SLOT(slotFinished()));
}
void MainWindow::slotError(QNetworkReply::NetworkError networkError)
{
qDebug() << "slotError";
}void MainWindow::slotFinished()
{
qDebug() << "slotError";
}
@Are you sure you use the slots keyword in the header? You can always check the return value for your connect(..) calls to make sure the slots and signals was found.
The fact that it runs in a separate thread should not be a problem I think. Specially not if all involved objects and owned by the same thread. -
all connect returens are true.
this is how my header looks like :
@#ifndef HttpClient
#define HttpClient
#include <QNetworkAccessManager>
#include <QtNetwork>
#include <QMutex>
#include <QUrl>QT_BEGIN_NAMESPACE
class QSslError;
class QAuthenticator;
class QNetworkReply;
QT_END_NAMESPACEclass HttpClient : public QObject
{
Q_OBJECTpublic:
HttpClient(QFile* file,QMutex* mutex);
~HttpClient();
void startRequest(QUrl url);public slots:
void httpFinished();
void httpReadyRead();
void updateDataReadProgress(qint64 bytesRead, qint64 totalBytes);
void slotAuthenticationRequired(QNetworkReply*,QAuthenticator *);
void slotError(QNetworkReply::NetworkError err);#ifndef QT_NO_OPENSSL
void sslErrors(QNetworkReply*,const QList<QSslError> &errors);
#endifprivate:
QUrl m_url;
QNetworkAccessManager* m_networkManager;
QNetworkReply *reply;
void HandleNetworkError(QNetworkReply::NetworkError& networkError,
QNetworkReply *networkReply);
};#endif@
-
Missed your update before. I have not been using the QThreadPool stuff in Qt so I do not know how it works but yea if the thread ends before the request is completed and the thread owns either the object that is sending or receiving the signal that you want it will not be delivered.
Maybe you should think about if you really need the threads for the task you are trying to perform. Since the QNetworkAccessManager is working asynchronous anyway it might not be needed.
-
I am sure there is a way to do it but I think that would violate the purpose of the QRunnable. QRunnable is more a "fire and forget" kind of thing. It seems it doesn't even have an event loop which you would need to handle your signals/slots.
I advice you to look at traditional QThread threads or maybe QtConcurrent if you still feel the need to actually use threads.