[SOLVED] QNetworkReply and lambda -- strange behaviour



  • Hi there!

    I'm trying to write a simple network function. Now it looks like that:

    @void NetworkManager::getClanInfoByTag(const QString &tag)
    {
    QNetworkRequest request = QNetworkRequest(QUrl(clanInfoUrl.arg(appId).arg(tag)));

    QNetworkReply* reply = m_manager->get(request);
    
    connect(reply, &QNetworkReply::finished, [this, reply]()
    {
        qDebug() << sender();
        qDebug() << reply->errorString();
        qDebug() << reply->readAll();
    
        emit clanInfoByTagCompleted(reply->readAll(),
                                    reply->error() == QNetworkReply::NoError);
    });
    
    reply->deleteLater();
    

    }@

    So, I'm simply trying to request data by some url and print it. I know, that QNetworkAccessManager is asynchronous, so I wrote lambda instead of separate slot...and it doesn't work. No data in output of program. However, if
    @reply->deleteLater()@

    is commented, then qDebug prints

    QObject(0x0)
    "Unknown error"
    some valid data

    m_manager is declared as QNetworkAccessManager* inside my NetworkManager class.

    What am I doing wrong?
    Should I write separate slot for that?
    Thanks to any help.


  • Lifetime Qt Champion

    Hi,

    You are calling deleteLater directly in getClanInfoByTag rather that in the lambda which means that at the next event loop iteration your reply will be deleted. deleteLater won't wait for the lambda to be called or the reply to finish.



  • [quote author="SGaist" date="1420321593"]Hi,

    You are calling deleteLater directly in getClanInfoByTag rather that in the lambda which means that at the next event loop iteration your reply will be deleted. deleteLater won't wait for the lambda to be called or the reply to finish.[/quote]

    Thanks, that seemes interesting! But after I've tried it, the output looks like in second case:

    QObject(0×0)
    “Unknown error”
    some valid data

    So, the problem is still present.



  • Shouldn't the third argument be a QObject? It looks like you only have three arguments.



  • Hi,

    What do you consider as a problem?

    If you consider that sender() returns a null pointer as a problem, according to the "documentation":http://doc.qt.io/qt-5/qobject.html#sender , it seems to be the expected behavior. sender() returns a valid pointer when called in a slot.

    By the way, since "reply" is captured in the lambda, you don't need sender(). You already have the sender of the signal, i.e. "reply".

    If you consider not receiving any data as a problem, than SGaist has already given the answer for that. You should put the reply->deleteLater() into the lambda. Otherwise you'll have a logical error by deleting the "reply" object before receiving any reply.

    As for the address of the "reply" object, replace the first line of the lambda as follows:
    @qDebug() << reply;@



  • Aha, there is another issue in your code: You are calling reply->readAll() twice. You should call it once and store the returned data in a variable and than you should use it twice:
    @
    ...
    QByteArray data = reply->readAll();
    qDebug() << data;
    emit clanInfoByTagCompleted(data, ...);
    ...
    @



  • [quote author="ckakman" date="1420325742"]Aha, there is another issue in your code: You are calling reply->readAll() twice. You should call it once and store the returned data in a variable and than you should use it twice:
    @
    ...
    QByteArray data = reply->readAll();
    qDebug() << data;
    emit clanInfoByTagCompleted(data, ...);
    ...
    @[/quote]

    No, that's just for debugging =)

    [quote author="ckakman" date="1420325513"]Hi,
    What do you consider as a problem?
    [/quote]

    The main problem here -- "Unknown error", while reply->readAll() gives me valid QByteArray =(

    [quote author="t3685" date="1420325393"]Shouldn't the third argument be a QObject? It looks like you only have three arguments.[/quote]

    Qt supports lambda functions as slot functions, and in that case, only 3 arguments will be provided. Otherwise, that code shouldn't be compiled =)



  • Look at the QIODevice "source code":https://qt.gitorious.org/qt/qtbase/source/73a1e8c60d894701f34806cc4b847aa2814bf389:src/corelib/io/qiodevice.cpp :line 1618

    If the error string is empty, "Unknown error" is returned. Apparently, you should call errorString() when error() returns something other than NoError. That makes sense.



  • [quote author="ckakman" date="1420329539"]Look at the QIODevice "source code":https://qt.gitorious.org/qt/qtbase/source/73a1e8c60d894701f34806cc4b847aa2814bf389:src/corelib/io/qiodevice.cpp :line 1618

    If the error string is empty, "Unknown error" is returned. Apparently, you should call errorString() when error() returns something other than NoError. That makes sense.[/quote]

    Oh, my fault. Thank you! Everything works fine.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.