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 without show() freezes program

QNetworkAccessManager without show() freezes program

Scheduled Pinned Locked Moved General and Desktop
10 Posts 2 Posters 2.5k Views
  • 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.
  • M Offline
    M Offline
    MrSanchez
    wrote on last edited by MrSanchez
    #1

    Hi,

    I have a member function (let's say: functionA) of a QDialog class (GUI) in which QNetworkAccessManager is used, like this:

    nam = new QNetworkAccessManager(this);
    

    In main.cpp I create the QDialog object (let's say: dialog). And I'd like to use the member function without showing the dialog GUI.
    However, calling the member function without first using show(), like this:

    dialog.functionA(); // function does execute, but then freezes at QNAM
    

    results in the application hanging at the QNetworkAccessManager line.

    What I do not understand is why I am able to solve the problem by showing and then hiding the GUI like this:

    dialog.show(); // briefly shows the gui
    dialog.hide(); // hides the gui again
    dialog.functionA(); // now all of a sudden it does work
    

    I suspect the problem has to do with threading but what does show() have to do with that?

    Is there a more efficient way for me to accomplish my goal other than show() followed by hide()? Because there is a visible delay between showing and hiding when using this method.

    Kind regards,
    Sanchez

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

      Hi, welcome to the forum.
      I don't think it has anything to do with threading or specifically showing/hiding a window.
      You're probably just using QNAM wrong. See if using qApp->processEvents() instead of show/hide fixes the problem. If it does then you're definitely doing it wrong.
      Show the code of functionA and specifically how you're handling the request and response so we can see what's going on.

      1 Reply Last reply
      0
      • M Offline
        M Offline
        MrSanchez
        wrote on last edited by MrSanchez
        #3

        Hi,

        The processEvents trick works. But I assume it would be unwise to use it?

        functionA (with the actual parameters this time):

        void dialog::functionA(const QString &username, const QString &uid)
        {
        QUrl url(m_someURL);
        QUrlQuery query;
        
        query.addQueryItem("username", username);
        query.addQueryItem("id", uid);
        
        url.setQuery(query.query());
        
        QNetworkRequest request(url);
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
        
        if(nam != NULL) delete nam; // removing this has no effect on the problem
        qDebug() << "nam1"; // shown
        nam = new QNetworkAccessManager(this);
        qDebug() << "nam2"; // never shown
        QObject::connect(nam, SIGNAL(finished(QNetworkReply*)),this, SLOT(replyFinished(QNetworkReply*)));
        qDebug() << "NAM created, send POST";
        
        QByteArray data;
        data.append(query.toString(QUrl::FullyEncoded).toUtf8());
        
        nam->post(request,data);
        }
        

        The nam in the dialog.h:

        private:
             QNetworkAccessManager *nam{NULL};
        

        After "nam1", the "nam2" debug output is never shown, so the code stops executing after the QNAM line.

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

          But I assume it would be unwise to use it?

          Yes, very. It won't work most of the time and neither the show/hide thing. Your request just happens to be real fast in your testing, but if it takes just a little bit longer and misses the call the app will hang just the same as without it.

          The root of the problem is elsewhere. QNAM needs a running event loop to properly deliver signals. Your app seems to not have one or it is in some way blocked. Usually there's an exec() call somewhere in your app that runs the loop. Do you have one?

          M 1 Reply Last reply
          0
          • Chris KawaC Chris Kawa

            But I assume it would be unwise to use it?

            Yes, very. It won't work most of the time and neither the show/hide thing. Your request just happens to be real fast in your testing, but if it takes just a little bit longer and misses the call the app will hang just the same as without it.

            The root of the problem is elsewhere. QNAM needs a running event loop to properly deliver signals. Your app seems to not have one or it is in some way blocked. Usually there's an exec() call somewhere in your app that runs the loop. Do you have one?

            M Offline
            M Offline
            MrSanchez
            wrote on last edited by
            #5

            @Chris-Kawa

            Other than a single occurence in my main function, nope.
            My main (main.cpp) function has 'return a.exec();' on the bottom, way below the section where I call functionA.
            This was default when I began developing this application a while ago and I don't think that could be the event loop right? Since that would only start running when the program got to the end of the main function.

            Kind regards,
            Sanchez

            Chris KawaC 1 Reply Last reply
            0
            • M MrSanchez

              @Chris-Kawa

              Other than a single occurence in my main function, nope.
              My main (main.cpp) function has 'return a.exec();' on the bottom, way below the section where I call functionA.
              This was default when I began developing this application a while ago and I don't think that could be the event loop right? Since that would only start running when the program got to the end of the main function.

              Kind regards,
              Sanchez

              Chris KawaC Offline
              Chris KawaC Offline
              Chris Kawa
              Lifetime Qt Champion
              wrote on last edited by Chris Kawa
              #6

              @MrSanchez said:

              I don't think that could be the event loop right? Since that would only start running when the program got to the end of the main function.

              That's exactly it. If you just put a bunch of code before it it will all execute sequentially and no non-direct signal/slot connections will ever work until you get to that line. If you happen to wait on some queued signal before it your app is as good as dead because no signal will ever be delivered if you don't enter that loop (unless you cheat with the tricks above, but that's like running a car on pure luck instead of gasoline ;) ).

              M 1 Reply Last reply
              0
              • Chris KawaC Chris Kawa

                @MrSanchez said:

                I don't think that could be the event loop right? Since that would only start running when the program got to the end of the main function.

                That's exactly it. If you just put a bunch of code before it it will all execute sequentially and no non-direct signal/slot connections will ever work until you get to that line. If you happen to wait on some queued signal before it your app is as good as dead because no signal will ever be delivered if you don't enter that loop (unless you cheat with the tricks above, but that's like running a car on pure luck instead of gasoline ;) ).

                M Offline
                M Offline
                MrSanchez
                wrote on last edited by
                #7

                @Chris-Kawa
                Ah, but now I am a bit lost on how to continue.
                I don't think I can start the event loop right at the beginning of main, so it will only start when it hit the end of main. So I imagine I can't have anything blocking the main function and thus blocking the start of the main event loop.

                The problem is, I need that event loop running before I execute most of my code.
                I did some searching, would putting most of my main function's code in a separate function and instead calling QTimer::singleShot work? The problem I see with that is that it needs a QObject, a class, and I'm dealing with this in main.cpp

                Any kick in the right direction would be appreciated loads :)

                Kind regards,
                Sanchez

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

                  would putting most of my main function's code in a separate function and instead calling QTimer::singleShot work?

                  You're missing the point. It doesn't matter if you put it before the loop starts or after it starts. The problem is that you're blocking, so there's nothing looping and nothing delivering queued signals/events.
                  So what you need to do is switch your thinking from this (in pseudocode):

                  getUserInput();
                  processUserInput();
                  startSomeRequest();
                  waitForItToFinish();
                  processResponse();
                  finishProgram();
                  

                  to something more like this:

                  connect(userInput, processUserInput);
                  connect(userInputProcessed, startSomeRequest);
                  connect(requestFinished, processResponse);
                  loop();
                  
                  M 1 Reply Last reply
                  1
                  • Chris KawaC Chris Kawa

                    would putting most of my main function's code in a separate function and instead calling QTimer::singleShot work?

                    You're missing the point. It doesn't matter if you put it before the loop starts or after it starts. The problem is that you're blocking, so there's nothing looping and nothing delivering queued signals/events.
                    So what you need to do is switch your thinking from this (in pseudocode):

                    getUserInput();
                    processUserInput();
                    startSomeRequest();
                    waitForItToFinish();
                    processResponse();
                    finishProgram();
                    

                    to something more like this:

                    connect(userInput, processUserInput);
                    connect(userInputProcessed, startSomeRequest);
                    connect(requestFinished, processResponse);
                    loop();
                    
                    M Offline
                    M Offline
                    MrSanchez
                    wrote on last edited by MrSanchez
                    #9

                    @Chris-Kawa
                    Hi,

                    Sorry for the late reply.
                    Thanks for the insight, you've shown me a way to change my mindset.
                    I'm relatively new to using connect (I know how to use it), I'll rewrite my functions to give it the fundamental role that it deserves :)
                    I'll post back when I get it working, once again cheers.

                    Kind regards,
                    Sanchez

                    1 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      MrSanchez
                      wrote on last edited by
                      #10

                      I've rewritten my program so now it no longer blocks and thus uses connect() where applicable. I did have to use singleShot for functionA() to make sure it executes after the event loop starts. Atleast won't have to use some hacky workaround like qApp->processevents() :)

                      Thanks for the help.

                      Kind regards,
                      Sanchez

                      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