Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QNetworkAccessManager doesn't emit finished without blocking current thread
Forum Updated to NodeBB v4.3 + New Features

QNetworkAccessManager doesn't emit finished without blocking current thread

Scheduled Pinned Locked Moved General and Desktop
21 Posts 5 Posters 9.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    blokant
    wrote on last edited by
    #1

    in some of my methods:
    @connect(nwam, SIGNAL(finished(QNetworkReply*)) , this, SLOT(processReply(QNetworkReply*)) );@

    processReply is @QByteArray ba = r->readAll();
    qDebug() << ba;@

    finished signal emits only if i do
    @
    QEventLoop eventLoop;
    connect(nwam, SIGNAL(finished(QNetworkReply *)), &eventLoop, SLOT(quit()));
    eventLoop.exec();
    @
    But it will block main thread.So, what I am doing wrong?

    1 Reply Last reply
    0
    • A Offline
      A Offline
      andreyc
      wrote on last edited by
      #2

      How do you send a request?
      Is it one of http requests or custom request?

      1 Reply Last reply
      0
      • JKSHJ Offline
        JKSHJ Offline
        JKSH
        Moderators
        wrote on last edited by
        #3

        Hi, and welcome to the Qt Dev Net!

        Which thread does your QNAM live in?

        Which thread runs processReply?

        How did you create + start your threads?

        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

        1 Reply Last reply
        0
        • B Offline
          B Offline
          blokant
          wrote on last edited by
          #4

          nwam->get(*request);
          [quote author="andreyc" date="1396197278"]How do you send a request?
          Is it one of http requests or custom request?[/quote]

          1 Reply Last reply
          0
          • B Offline
            B Offline
            blokant
            wrote on last edited by
            #5

            i don't use my own threads, i do all the things inside main thread because , as i can see, QNAM is async by design
            [quote author="JKSH" date="1396218189"]Hi, and welcome to the Qt Dev Net!

            Which thread does your QNAM live in?

            Which thread runs processReply?

            How did you create + start your threads?[/quote]

            1 Reply Last reply
            0
            • Chris KawaC Offline
              Chris KawaC Offline
              Chris Kawa
              Lifetime Qt Champion
              wrote on last edited by
              #6

              QNAM itself is async, but signal delivery relies on a working event loop.

              Qt is event driven, so you should be running all your code inside an event loop, especially if you want to receive events and fire slots.
              Don't think in terms "my program runs code from top to bottom but hangs at exec(). You should rather think "my program spins inside exec() and notifies me via slots and event handlers when something happens".

              1 Reply Last reply
              0
              • JKSHJ Offline
                JKSHJ Offline
                JKSH
                Moderators
                wrote on last edited by
                #7

                To add to Chris: Your main thread needs a running event loop in order for QNAM to work. That means you must call QCoreApplication::exec() -- or else no signals and slots will be processed.

                Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                1 Reply Last reply
                0
                • B Offline
                  B Offline
                  blokant
                  wrote on last edited by
                  #8

                  So, do you mean that i have to write something like this?
                  @
                  nwam->get(request);
                  connect(nwam, SIGNAL(finished(QNetworkReply
                  )) , this, SLOT(processTaskListsReply(QNetworkReply*)) );

                  QEventLoop eventLoop;
                  connect(nwam, SIGNAL(finished(QNetworkReply *)), &eventLoop, SLOT(quit()));
                  eventLoop.exec();
                  @

                  1 Reply Last reply
                  0
                  • X Offline
                    X Offline
                    Xander84
                    wrote on last edited by
                    #9

                    Why do you use your own QEventLoop anyways? Don't you have a QCoreApplication running in your program?

                    1 Reply Last reply
                    0
                    • B Offline
                      B Offline
                      blokant
                      wrote on last edited by
                      #10

                      I have typical main.cpp in my project
                      @
                      int main(int argc, char *argv[])
                      {
                      QApplication a(argc, argv);
                      Dialog w;
                      w.show();
                      return a.exec();
                      }
                      @
                      And i have separate class, which use QNAM

                      1 Reply Last reply
                      0
                      • X Offline
                        X Offline
                        Xander84
                        wrote on last edited by
                        #11

                        then you should not need a second QEventLoop (QApplication already has a QEventLoop internally), that might be the problem why your signals and slots are not working as they should.
                        The QApplication is usually a global object in your application, you can access it with the global pointer qApp from anywhere if you need to.

                        So it should not matter if you create the QNAM from your Dialog or in the main.cpp or whatever, you don't need to create a QEventLoop yourself for it to work.

                        1 Reply Last reply
                        0
                        • B Offline
                          B Offline
                          blokant
                          wrote on last edited by
                          #12

                          well, then .. why it does not work properly? If i use my QEventloop i see that it freeze a little bit but it works

                          1 Reply Last reply
                          0
                          • Chris KawaC Offline
                            Chris KawaC Offline
                            Chris Kawa
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            Hard to tell with the information you gave. Maybe you're deleting the receiving object before the finish signal fires? And since you put additional blocking exec() it works.
                            Some more context and code would be helpful.

                            1 Reply Last reply
                            0
                            • B Offline
                              B Offline
                              blokant
                              wrote on last edited by
                              #14

                              @
                              QNetworkAccessManager *nwam = new QNetworkAccessManager();
                              QNetworkRequest request = new QNetworkRequest(QUrl(listUrl));
                              request->setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
                              nwam->get(request);
                              connect(nwam, SIGNAL(finished(QNetworkReply
                              )) , this, SLOT(processTaskListsReply(QNetworkReply
                              )) );

                              @
                              @
                              processTaskListsReply(QNetworkReply *r)
                              {
                              qDebug() << "processTaskListsReply();";
                              QByteArray ba = r->readAll();
                              qDebug() << ba;
                              }
                              @

                              1 Reply Last reply
                              0
                              • Chris KawaC Offline
                                Chris KawaC Offline
                                Chris Kawa
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                I meant the context of it. Where is it created. What is the lifetime of the object it holds these. Where is the nwam deleted etc.

                                1 Reply Last reply
                                0
                                • X Offline
                                  X Offline
                                  Xander84
                                  wrote on last edited by
                                  #16

                                  it almost looks like you create a new QNetworkAccessManager for every request? hard to tell from your snippet but that is not a very good idea.

                                  If you read the doc of QNAM it says one object per app should be sufficient in most cases, so usually you have one global QNAM and there is no need to create it on the heap (with new).

                                  What I would do, if you onyl have one Dialog in your app then just create an object in there:
                                  @
                                  class Dialog : public QDialog
                                  {
                                  Q_OBJECT
                                  private:
                                  QNetworkAccessManager m_networkManager;
                                  };
                                  @
                                  and then connect the signals of m_networkManager in the constructor of the Dialog only once and reuse the QNAM for all requests. Unless you only need the QNAM in rare cases this would be a better way I think.

                                  1 Reply Last reply
                                  0
                                  • B Offline
                                    B Offline
                                    blokant
                                    wrote on last edited by
                                    #17

                                    ou, i see: i have to use only the one QNAM for all classes of my app. Thanks, i will try it later

                                    1 Reply Last reply
                                    0
                                    • X Offline
                                      X Offline
                                      Xander84
                                      wrote on last edited by
                                      #18

                                      You don't have to use only one instance, but it would be considered best practice to only have one, because the QNAM initialization might be expensive and it also caches many things like DNS resolution etc, if you create a new one every time that cache will be lost and network requests take longer.
                                      There was a nice talk about it, if you want take a look I found it very interesting. "QtDD13 - Peter Hartmann - Speeding up your Qt app with new QtNetwork features":https://www.youtube.com/watch?v=OM9BgcXr9ys&list=LLa69qk-_WIRna0JNQf8Md0w.

                                      1 Reply Last reply
                                      0
                                      • B Offline
                                        B Offline
                                        blokant
                                        wrote on last edited by
                                        #19

                                        ou, thanks, i will try to watch all that videos if i will get time. I will use Singleton

                                        1 Reply Last reply
                                        0
                                        • B Offline
                                          B Offline
                                          blokant
                                          wrote on last edited by
                                          #20

                                          Singleton may be not so good idea, i found this

                                          @
                                          DbHandler* dbHandler = new DbHandler;

                                          // Make your DbHandler* globally accessible by settings it as a
                                          // dynamic property of the application object.
                                          
                                          application.setProperty("dbHandler", QVariant::fromValue<DbHandler*>(dbHandler));
                                          
                                          ....
                                          

                                          }

                                          void SomeObject::someMethod()
                                          {
                                          DbHandler* dbHandler = qApp->property("dbHandler").value<DbHandler*>();
                                          }
                                          @

                                          But... what if i wand to split a part of my app as library later, then i will get dependency injection: users will have to give QNAM instance to my constructor, is it right way?

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved