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. Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?

Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?

Scheduled Pinned Locked Moved Solved General and Desktop
networkhttpmacos
18 Posts 4 Posters 2.2k 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.
  • SprezzaturaS Sprezzatura

    I'm sorry for being slow, but I'm new at Qt.

    I am not versed in Lambdas, so this is what I tried:

    bool bDoneStats = false;
    void doneStats(QNetworkReply *reply)
    {
    	bDoneStats = true;          // never gets here
    	qDebug()<<"doneStats\n";
    }
    
    void MainWindow::closeEvent(QCloseEvent *event)
    {
    	QNetworkReply *reply;
            QString urlStr("https://foo.com/bar.php?some&data");
    	QUrl url(urlStr);
    	if(!url.isValid())
    	{	QString urlError = url.errorString();
    		qDebug() << "\n" << urlError << "\n";
    	}
    	QNetworkRequest *request = new QNetworkRequest(url);
    	request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
    	QByteArray content = urlStr;
    
    	QNetworkAccessManager *nam = new QNetworkAccessManager;
    	if(request != NULL && nam != NULL )
    	{	reply = nam->post(*request, content);
                   // also tried "SIGNAL(finished(QNetworkReply*))"
    		connect(nam, SIGNAL(nam->finished(QNetworkReply*)), this, SLOT(doneStats(QNetworkReply*)));
    		QNetworkReply::NetworkError netret = reply->error();
    		qDebug() << "\nSuccess " << url << " NetworkError " << netret << "\n";
    	}
    
    	do
    	{} while (!bDoneStats);     // never breaks loop
    
    	event->accept();
    	QMainWindow::closeEvent(event);
    }
    

    It never reaches "doneStats", and goes into an endless loop. If I remove the do/while, it exits the function but nothing is written at the server.

    What am I missing? I really appreciate your help.

    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by
    #7

    @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

    do
    {} while (!bDoneStats);     // never breaks loop
    

    When you get your code compiling (as per @Pl45m4's comment), what is this code about?? You won't want any such tight loop....

    SprezzaturaS 2 Replies Last reply
    0
    • SprezzaturaS Offline
      SprezzaturaS Offline
      Sprezzatura
      wrote on last edited by Sprezzatura
      #8

      This is the revised code. It still does not call 'doneStats', and does not write to the server.

      I am using Qt 5.12, because I need to be compatible with older versions of macOS.

      void MainWindow::doneStats(QNetworkReply *reply)
      {
      	bDoneStats = true;		// member of MainWindow
      	qDebug()<<"doneStats\n";
      }
      
      void MainWindow::closeEvent(QCloseEvent *event)
      {
      	bDoneStats = false;
      	QNetworkReply *reply;
      	const char *urlStr("https://foo.com/bar.php?some&data");
      	QUrl url(urlStr);
      	if(!url.isValid())
      	{	QString urlError = url.errorString();
      		qDebug() << "\n" << urlError << "\n";
      	}
      	QNetworkRequest *request = new QNetworkRequest(url);
      	request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
      	QByteArray content(urlStr);
      
      	QNetworkAccessManager *nam = new QNetworkAccessManager;
      	if(request != NULL && nam != NULL )
      	{	reply = nam->post(*request, content);
      		connect(nam, &QNetworkAccessManager::finished, this, &MainWindow::doneStats);
      		QNetworkReply::NetworkError netret = reply->error();	// QNetworkReply::NoError
      		qDebug() << "\nSuccess " << url << " NetworkError " << netret << "\n";
      	}
      
      	event->accept();
      	QMainWindow::closeEvent(event);
      }
      
      1 Reply Last reply
      0
      • JonBJ JonB

        @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

        do
        {} while (!bDoneStats);     // never breaks loop
        

        When you get your code compiling (as per @Pl45m4's comment), what is this code about?? You won't want any such tight loop....

        SprezzaturaS Offline
        SprezzaturaS Offline
        Sprezzatura
        wrote on last edited by
        #9
        This post is deleted!
        1 Reply Last reply
        0
        • JonBJ JonB

          @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

          do
          {} while (!bDoneStats);     // never breaks loop
          

          When you get your code compiling (as per @Pl45m4's comment), what is this code about?? You won't want any such tight loop....

          SprezzaturaS Offline
          SprezzaturaS Offline
          Sprezzatura
          wrote on last edited by
          #10

          @JonB said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

          @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

          do
          {} while (!bDoneStats);     // never breaks loop
          

          When you get your code compiling (as per @Pl45m4's comment), what is this code about?? You won't want any such tight loop....

          I am expecting 'bDoneStats' to be set to true by the callback or SLOT function, thus breaking the loop.

          JonBJ 1 Reply Last reply
          0
          • SprezzaturaS Offline
            SprezzaturaS Offline
            Sprezzatura
            wrote on last edited by Sprezzatura
            #11

            @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

            I just realized I called 'connect' after the post, I will change the order and try again.

            1 Reply Last reply
            0
            • SprezzaturaS Sprezzatura

              @JonB said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

              @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

              do
              {} while (!bDoneStats);     // never breaks loop
              

              When you get your code compiling (as per @Pl45m4's comment), what is this code about?? You won't want any such tight loop....

              I am expecting 'bDoneStats' to be set to true by the callback or SLOT function, thus breaking the loop.

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #12

              @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

              I am expecting 'bDoneStats' to be set to true by the callback or SLOT function, thus breaking the loop.

              This absolutely will not happen. Rather, your program will use up CPU time forever here, contributing to the entropy of The Universe :)

              There are no multiple threads threads here. No signals or slots will fire while your loop executes. You will need a "wait for" event loop here instead, because you don't want to accept the original close event until this has completed. Look at QEventLoop::exec(). I don't know if there are consequences of calling this while inside MainWindow::closeEvent().

              1 Reply Last reply
              0
              • SprezzaturaS Offline
                SprezzaturaS Offline
                Sprezzatura
                wrote on last edited by
                #13

                I've removed the do/while loop, I have re-ordered these statements:

                  connect(nam, &QNetworkAccessManager::finished, this, &MainWindow::doneStats);
                  reply = nam->post(*request, content);
                

                This is part of an application that otherwise runs fine. 'exec' is called in another part of the program (main.cpp).

                The code works if invoked at the beginning of the program. It only seems to fail when it is called at the end of a session.

                What do I need to do to get it to work?

                JonBJ 1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #14

                  Hi,

                  One way is to use a local QEventLoop to wait for the request to complete. However, does it really make sense to do it there ? It sounds rather like something that should be done in the main method at application end.

                  In any case, there's no need to allocate QNetworkRequest on the heap.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  SprezzaturaS 1 Reply Last reply
                  1
                  • SprezzaturaS Sprezzatura

                    I've removed the do/while loop, I have re-ordered these statements:

                      connect(nam, &QNetworkAccessManager::finished, this, &MainWindow::doneStats);
                      reply = nam->post(*request, content);
                    

                    This is part of an application that otherwise runs fine. 'exec' is called in another part of the program (main.cpp).

                    The code works if invoked at the beginning of the program. It only seems to fail when it is called at the end of a session.

                    What do I need to do to get it to work?

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #15

                    @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                    'exec' is called in another part of the program (main.cpp).

                    I was talking about you putting an event loop here in your code:

                    QEventLoop loop;
                    loop.exec();
                    

                    That's how you have to do a "wait for", when you really need to, in Qt stuff.

                    1 Reply Last reply
                    0
                    • SGaistS SGaist

                      Hi,

                      One way is to use a local QEventLoop to wait for the request to complete. However, does it really make sense to do it there ? It sounds rather like something that should be done in the main method at application end.

                      In any case, there's no need to allocate QNetworkRequest on the heap.

                      SprezzaturaS Offline
                      SprezzaturaS Offline
                      Sprezzatura
                      wrote on last edited by
                      #16

                      @SGaist said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                      Hi,

                      One way is to use a local QEventLoop to wait for the request to complete. However, does it really make sense to do it there ? It sounds rather like something that should be done in the main method at application end.

                      YES! That's one of the solutions I tried to do, but couldn't figure out where to do it. Where, in the code, can I intercept an application 'quit', prior to closeEvent?

                      1 Reply Last reply
                      0
                      • SprezzaturaS Offline
                        SprezzaturaS Offline
                        Sprezzatura
                        wrote on last edited by Sprezzatura
                        #17

                        OK, here is the final, working solution. I am new to Qt and am not familiar with QEventLoop. I needed to see how the whole thing fitted together in order to understand.

                        void MainWindow::closeEvent(QCloseEvent *event)
                        {
                        	QNetworkReply *reply;
                        	QUrl url("https://foo.com/bar.php?some&data");
                        	if(!url.isValid())
                        	{	QString urlError = url.errorString();
                        		qDebug() << "\n" << urlError << "\n";
                        	}
                        	QNetworkRequest *request = new QNetworkRequest(url);
                        	request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
                        	QByteArray content = "https://foo.com/bar.php?some&data";
                        	QNetworkAccessManager *nam = new QNetworkAccessManager;
                        
                        	if(request != NULL && nam != NULL )
                        	{	QEventLoop loop;
                        		// https://www.codeproject.com/Questions/1196636/Qnetworkaccesmanager-doesn-t-emit-finished-signal
                        		connect (nam, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit()), Qt::DirectConnection);
                        		reply = nam->post(*request, content);
                        		loop.exec();
                        
                        		QNetworkReply::NetworkError netret = reply->error();
                        		qDebug() << "\nSuccess " << url << " NetworkError " << netret << "\n";
                        		QList<QByteArray> headers = reply->rawHeaderList();
                        		QList<QByteArray>::iterator hit;
                        		for(hit = headers.begin(); hit != headers.end(); hit++)	// is empty if failed
                        			qDebug() << *hit << reply->rawHeader(*hit);
                        	}
                        
                        	event->accept();
                        
                        	QMainWindow::closeEvent(event);
                        }
                        

                        Thank you profusely @Pl45m4, @JonB and @SGaist .

                        JonBJ 1 Reply Last reply
                        0
                        • SprezzaturaS Sprezzatura

                          OK, here is the final, working solution. I am new to Qt and am not familiar with QEventLoop. I needed to see how the whole thing fitted together in order to understand.

                          void MainWindow::closeEvent(QCloseEvent *event)
                          {
                          	QNetworkReply *reply;
                          	QUrl url("https://foo.com/bar.php?some&data");
                          	if(!url.isValid())
                          	{	QString urlError = url.errorString();
                          		qDebug() << "\n" << urlError << "\n";
                          	}
                          	QNetworkRequest *request = new QNetworkRequest(url);
                          	request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
                          	QByteArray content = "https://foo.com/bar.php?some&data";
                          	QNetworkAccessManager *nam = new QNetworkAccessManager;
                          
                          	if(request != NULL && nam != NULL )
                          	{	QEventLoop loop;
                          		// https://www.codeproject.com/Questions/1196636/Qnetworkaccesmanager-doesn-t-emit-finished-signal
                          		connect (nam, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit()), Qt::DirectConnection);
                          		reply = nam->post(*request, content);
                          		loop.exec();
                          
                          		QNetworkReply::NetworkError netret = reply->error();
                          		qDebug() << "\nSuccess " << url << " NetworkError " << netret << "\n";
                          		QList<QByteArray> headers = reply->rawHeaderList();
                          		QList<QByteArray>::iterator hit;
                          		for(hit = headers.begin(); hit != headers.end(); hit++)	// is empty if failed
                          			qDebug() << *hit << reply->rawHeader(*hit);
                          	}
                          
                          	event->accept();
                          
                          	QMainWindow::closeEvent(event);
                          }
                          

                          Thank you profusely @Pl45m4, @JonB and @SGaist .

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by
                          #18

                          @Sprezzatura
                          I think this looks better :)

                          Your code as it stands presumably leaks QNetworkRequest *request = new QNetworkRequest(url); and QNetworkAccessManager *nam = new QNetworkAccessManager;. You could put these on the stack (no pointers, no new). And I think you're supposed to deleteLater() the QNetworkReply *reply = nam->post(*request, content);.

                          You can get away without, but one day when you want examine your code for memory leaks with e.g. valgrind it will be better.

                          1 Reply Last reply
                          1

                          • Login

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