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. How can I wait all request complate?
QtWS25 Last Chance

How can I wait all request complate?

Scheduled Pinned Locked Moved Unsolved General and Desktop
qnetworkreplyqnetworkrequestwait
3 Posts 2 Posters 233 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.
  • J Offline
    J Offline
    Joe von Habsburg
    wrote on 22 Mar 2024, 08:49 last edited by Joe von Habsburg
    #1

    There is a continuous data arrival to my Class1 class. I want to get another list by sending myArray list in the doSth function of Class1 to the getList function of Class2.

    Class2 should return me a list by making GET and PUT requests in the getList function. But I want to wait until these requests are completed, how can I do that?

    I have classes and structs

    //Class4

    struct Class4{
    int a;
    int b;
    }
    

    //Class3

    struct Class3{
    QString name;
    }
    

    //Class2

    #include "class3.h"
    #include "class4.h"
    
    enum Type{
    type1,
    type2,
    type3
    }
    
    class Class2:public QObject{
    Class2(){
    manager.setAutoDeleteReplies(true);
    }
    ~Class2(){
    reply->deleteLater();
    }
    
    QList<Class4> getList(QList<Class3> array){
    myList.clear();
    
    process1(1);
    
    for(Class3 class3 : array){
    process2(class3.name);
    getData();
    }
    
    process2("Joe Doe");
    process1(2);
    return myList;
    }
    
    private slots:
    void onReadReady(){
    if(type == Type::type3){
    data += reply->readAll();
    }
    }
    void onFinished(){
    if(type == Type::type3){
    Class4 class4 = getClass(data);
    myList.append(class4);
    }
    }
    
    
    private:
    void process1(int mode){
    type = Type::type1;
    QJsonObject data;
    data["mode"] = mode;
    QJsonDocument doc(data);
    QByteArray body = doc.toJson();
    QUrl url("http/url");
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    reply = manager.put(request, body);
    connect(reply, &QNetworkReply::readyRead, this, &Class2::onReadReady);
    connect(reply, &QNetworkReply::finished, this, &Class2::onFinished);
    }
    
    void process2(QString name){
    type = Type::type2;
    QJsonObject data;
    data["name"] = name;
    QJsonDocument doc(data);
    QByteArray body = doc.toJson();
    QUrl url("http/url2");
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    reply = manager.put(request, body);
    connect(reply, &QNetworkReply::readyRead, this, &Class2::onReadReady);
    connect(reply, &QNetworkReply::finished, this, &Class2::onFinished);
    }
    
    void getData(){
    type = Type::type3;
    QUrl url("http/url3");
    QNetworkRequest request(url);
    reply = manager.get(request);
    connect(reply, &QNetworkReply::readyRead, this, &Class2::onReadReady);
    connect(reply, &QNetworkReply::finished, this, &Class2::onFinished);
    }
    
    Class4 getClass(QByteArray data){
    Class4 class4;
    if(data.isNull() || data.size() <= 4){
    return class4;
    }
    QJsonDocument document = QJsonDocument:: fromJson(data);
    QJsonObject rootObj = document.object();
    class4.a= rootObj["a"].toInt();
    class4.b= rootObj["b"].toInt();
    return class4;
    }
    
    private:
    QNetworkReply *reply;
    QNetworkAccessManager manager;
    QByteArray data;
    QList<Class4> myArray;
    Type type = Type::type1;
    }
    

    //Class1

    #include "class2.h"
    #include "class3.h"
    #include "class4.h"
    
    class Class1 : public QObject{
    Class1();
    ~Class1();
    
    public slots:
    void doSth(QByteArray data){
    ... 
    //I want to wait here for response all request
    QList<Class4> result = class2.getList(myArray);
    ...
    }
    
    private:
    Class2 class2;
    QList<Class3> myArray;
    }
    

    //main

    #include "class1.h"
    
    int main(){
    Class1 class1;
    while(true){
    class1.doSth(data);
    }
    }
    
    J 1 Reply Last reply 22 Mar 2024, 09:11
    0
    • J Joe von Habsburg
      22 Mar 2024, 08:49

      There is a continuous data arrival to my Class1 class. I want to get another list by sending myArray list in the doSth function of Class1 to the getList function of Class2.

      Class2 should return me a list by making GET and PUT requests in the getList function. But I want to wait until these requests are completed, how can I do that?

      I have classes and structs

      //Class4

      struct Class4{
      int a;
      int b;
      }
      

      //Class3

      struct Class3{
      QString name;
      }
      

      //Class2

      #include "class3.h"
      #include "class4.h"
      
      enum Type{
      type1,
      type2,
      type3
      }
      
      class Class2:public QObject{
      Class2(){
      manager.setAutoDeleteReplies(true);
      }
      ~Class2(){
      reply->deleteLater();
      }
      
      QList<Class4> getList(QList<Class3> array){
      myList.clear();
      
      process1(1);
      
      for(Class3 class3 : array){
      process2(class3.name);
      getData();
      }
      
      process2("Joe Doe");
      process1(2);
      return myList;
      }
      
      private slots:
      void onReadReady(){
      if(type == Type::type3){
      data += reply->readAll();
      }
      }
      void onFinished(){
      if(type == Type::type3){
      Class4 class4 = getClass(data);
      myList.append(class4);
      }
      }
      
      
      private:
      void process1(int mode){
      type = Type::type1;
      QJsonObject data;
      data["mode"] = mode;
      QJsonDocument doc(data);
      QByteArray body = doc.toJson();
      QUrl url("http/url");
      QNetworkRequest request(url);
      request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
      reply = manager.put(request, body);
      connect(reply, &QNetworkReply::readyRead, this, &Class2::onReadReady);
      connect(reply, &QNetworkReply::finished, this, &Class2::onFinished);
      }
      
      void process2(QString name){
      type = Type::type2;
      QJsonObject data;
      data["name"] = name;
      QJsonDocument doc(data);
      QByteArray body = doc.toJson();
      QUrl url("http/url2");
      QNetworkRequest request(url);
      request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
      reply = manager.put(request, body);
      connect(reply, &QNetworkReply::readyRead, this, &Class2::onReadReady);
      connect(reply, &QNetworkReply::finished, this, &Class2::onFinished);
      }
      
      void getData(){
      type = Type::type3;
      QUrl url("http/url3");
      QNetworkRequest request(url);
      reply = manager.get(request);
      connect(reply, &QNetworkReply::readyRead, this, &Class2::onReadReady);
      connect(reply, &QNetworkReply::finished, this, &Class2::onFinished);
      }
      
      Class4 getClass(QByteArray data){
      Class4 class4;
      if(data.isNull() || data.size() <= 4){
      return class4;
      }
      QJsonDocument document = QJsonDocument:: fromJson(data);
      QJsonObject rootObj = document.object();
      class4.a= rootObj["a"].toInt();
      class4.b= rootObj["b"].toInt();
      return class4;
      }
      
      private:
      QNetworkReply *reply;
      QNetworkAccessManager manager;
      QByteArray data;
      QList<Class4> myArray;
      Type type = Type::type1;
      }
      

      //Class1

      #include "class2.h"
      #include "class3.h"
      #include "class4.h"
      
      class Class1 : public QObject{
      Class1();
      ~Class1();
      
      public slots:
      void doSth(QByteArray data){
      ... 
      //I want to wait here for response all request
      QList<Class4> result = class2.getList(myArray);
      ...
      }
      
      private:
      Class2 class2;
      QList<Class3> myArray;
      }
      

      //main

      #include "class1.h"
      
      int main(){
      Class1 class1;
      while(true){
      class1.doSth(data);
      }
      }
      
      J Offline
      J Offline
      JonB
      wrote on 22 Mar 2024, 09:11 last edited by JonB
      #2

      @Joe-von-Habsburg
      Leaving aside that your main() is no good for a Qt program, you have not created any Qt application instance and you should start the event loop. But I will stick to the nub of the question.

      This is a similar/related question to the currently on-going discussion in https://forum.qt.io/topic/155475/avoiding-event-loop-blockage-in-qt-applications, which you might like to read.

      The way most of us as Qt users would do it is not to wait till requests are complete. Instead we would write the code to execute after the response is received in a slot attached to QNetworkReply::finished. Do you see how that avoids any "while" loops and "waiting"? If necessary we would maintain state for where we got to and/or a queue of further requests to work through. This is the "event-driven" paradigm espoused by Qt and other similar systems.

      But if you really want to write your code to "block" and "wait" for a response, use a local QEventLoop instance and call exec(). This is at least an "efficient" way to do it. A couple of examples on stackoverflow illustrating just this for your QNetworkReply::finished case:
      https://stackoverflow.com/questions/29449561/qeventloop-proper-usage
      https://stackoverflow.com/questions/54694312/qeventloop-wait-for-only-local-events-not-main-loop-events

      This is the paradigm:

          QEventLoop localEventLoop;
          QNetworkAccessManager manager;
          QNetworkReply *reply = manager.get(QNetworkRequest(QUrl("http://example.com")));
          QObject::connect(reply, &QNetworkReply::finished, &localEventLoop, &QEventLoop::quit);
          localEventLoop.exec();
          // We do not get here until `QNetworkReply::finished` signal has been received, which quits the event loop
      
      J 1 Reply Last reply 22 Mar 2024, 09:23
      1
      • J JonB
        22 Mar 2024, 09:11

        @Joe-von-Habsburg
        Leaving aside that your main() is no good for a Qt program, you have not created any Qt application instance and you should start the event loop. But I will stick to the nub of the question.

        This is a similar/related question to the currently on-going discussion in https://forum.qt.io/topic/155475/avoiding-event-loop-blockage-in-qt-applications, which you might like to read.

        The way most of us as Qt users would do it is not to wait till requests are complete. Instead we would write the code to execute after the response is received in a slot attached to QNetworkReply::finished. Do you see how that avoids any "while" loops and "waiting"? If necessary we would maintain state for where we got to and/or a queue of further requests to work through. This is the "event-driven" paradigm espoused by Qt and other similar systems.

        But if you really want to write your code to "block" and "wait" for a response, use a local QEventLoop instance and call exec(). This is at least an "efficient" way to do it. A couple of examples on stackoverflow illustrating just this for your QNetworkReply::finished case:
        https://stackoverflow.com/questions/29449561/qeventloop-proper-usage
        https://stackoverflow.com/questions/54694312/qeventloop-wait-for-only-local-events-not-main-loop-events

        This is the paradigm:

            QEventLoop localEventLoop;
            QNetworkAccessManager manager;
            QNetworkReply *reply = manager.get(QNetworkRequest(QUrl("http://example.com")));
            QObject::connect(reply, &QNetworkReply::finished, &localEventLoop, &QEventLoop::quit);
            localEventLoop.exec();
            // We do not get here until `QNetworkReply::finished` signal has been received, which quits the event loop
        
        J Offline
        J Offline
        Joe von Habsburg
        wrote on 22 Mar 2024, 09:23 last edited by
        #3

        @JonB said in How can I wait all request complate?:

        main() is no good for a Qt program

        I gave main() as an example. To show that there is a continuous data flow to the doSth function.

        @JonB said in How can I wait all request complate?:

        But if you really want to write your code to "block" and "wait" for a response, use a local QEventLoop instance and call exec(). This is at least an "efficient" way to do it. A couple of examples on stackoverflow illustrating just this for your QNetworkReply::finished case:
        https://stackoverflow.com/questions/29449561/qeventloop-proper-usage
        https://stackoverflow.com/questions/54694312/qeventloop-wait-for-only-local-events-not-main-loop-events

        Thank you I will look them

        1 Reply Last reply
        0

        1/3

        22 Mar 2024, 08:49

        • Login

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