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. Error: no such slot while using QNetworkAccessManager with threads
Forum Updated to NodeBB v4.3 + New Features

Error: no such slot while using QNetworkAccessManager with threads

Scheduled Pinned Locked Moved General and Desktop
10 Posts 4 Posters 6.1k 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.
  • Z Offline
    Z Offline
    Zain
    wrote on last edited by
    #1

    0 down vote favorite

    I am in troubled situation on using QNetworkAccessManager in QThread. The same functions working fine without using threads. I am currently using only one thread and I need to add few more also.

    It fires error message : "Object::connect: No such slot QThread::replyFinished(QNetworkrReply*)"

    The header file code (NewThread.h ) is:
    @
    class NewThread: public QThread
    {
    public slots:
    void replyFinished(QNetworkReply* reply);

    protected:
         void run();
    
    private: 
    

    };
    @

    The source code file(NewThread.cpp ):
    @
    void NewThread::replyFinished(QNetworkReply *net_reply)
    {
    QByteArray data = net_reply->readAll();
    QString str(data);
    }

    void NewThread::run()
    {

    QNetworkAccessManager *manager;
    manager = new QNetworkAccessManager ();
    QNetworkRequest req;
    req.setUrl(QUrl("My url"));

        QByteArray postData;
    
        postData.append("some data string");
    
    
        req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
    
        manager->setCookieJar(new QNetworkCookieJar(manager));
        //Define the Request-url:
        connect (manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(replyFinish (QNetworkReply  *)));
        //Send the request:
        manager->post(req, postData);
    

    }

    void NewThread::replyFinish(QNetworkReply *reply)
    {
    QString answer = QString::fromUtf8(reply->readAll());
    qDebug () << answer;
    }
    @

    I am creating an object of NewThread class in another class, like below:

    @

    NewThread thread1;
    thread1.start();

    @

    I am wondering why the same code working without threads and not with threads. I am in hard situation, any help appreciated.

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mlong
      wrote on last edited by
      #2

      You don't have a Q_OBJECT macro in your class header.

      Edit to add:

      Also, what is your reasoning for using QThread with QNetworkAccessManager? QNAM is already asynchronous, and typically isn't necessary.

      (Also, subclassing QThread is not the preferred method of using QThreads)

      Software Engineer
      My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

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

        [quote author="mlong" date="1350574118"](Also, subclassing QThread is not the preferred method of using QThreads)[/quote]Following up on mlong's comment: The preferred way is shown at http://doc-snapshot.qt-project.org/5.0/qthread.html (that is Qt5 documentation, but most of it is applicable to Qt4.5 and above)

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

        1 Reply Last reply
        0
        • K Offline
          K Offline
          KA51O
          wrote on last edited by
          #4

          The new QThread documentation really is is a great improvement over the old one. Great job JKSH!

          1 Reply Last reply
          0
          • Z Offline
            Z Offline
            Zain
            wrote on last edited by
            #5

            @mlong, thanks for the reply.
            I used the Q_OBJECT macro and it resolved the error....BUT now the replyFinish slot(finished signal) is not working (it never get called) .
            When I checked the debug details it says.. invalid rpc server exception..
            I am unable to get that why on the earth is this exception firing here in threads and every thing working fine without threads.. I really need to do it with threads.
            Any suggestions...

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

              @KA510: Thanks for your kind words :) It was a community effort though; people on the forum and mailing list gave lots of helpful advice and insight

              @Zain: Some questions --

              Which class throws the exception? Your code doesn't show it

              Can you please provide more details on WHAT needs to be done with threads? Your example only sends a HTTP post request from your thread. But, I believe QNetworkAccessManager already does that in a separate thread.

              Also, take note: Your NewThread object was created in the MAIN thread, so NewThread::replyfinished() will execute in the MAIN thread (not the thread which contains QNetworkAccessManager!)

              Subclassing QThread is a bad idea, and adding slots to a subclass causes lots of problems. If you really want to create your own thread, I recommend reading the first example at http://doc-snapshot.qt-project.org/5.0/qthread.html ("Detailed Description")

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

              1 Reply Last reply
              0
              • Z Offline
                Z Offline
                Zain
                wrote on last edited by
                #7

                Thank you all for your efforts.

                I have done some exploration on this issue, and got a strange solution of adding a moc*.cpp file to the classes. And I actually got one in my debug folder. Please suggest:

                1. Will this work?
                2. how to add an external moc file to the project?

                I have copied it to project folder and added it to .pro as well.
                But it shows so many multiple declaration errors. (perhaps as many declaration as in moc file).

                Also clear if this is not going to work.

                @ JKSH, Its the same class (NetThread) which is showing the error.
                I want to get page source from url, as it should run in back ground because the post data will change and every time it will get different page source (I will run the thread, more than one time). During this process I need the program GUI user interface free for other things.
                Any suggestions.

                Thanks in advance

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

                  Qt reads your source code, and automatically generates moc*.cpp files. You cannot add "external" moc*.cpp files. You never need to add "external" moc*.cpp files.

                  Qt classes do not throw exceptions, so I'm guessing that the exception was thrown by code which you haven't shown us.

                  [quote author="Zain" date="1350656433"]I want to get page source from url, as it should run in back ground because the post data will change and every time it will get different page source (I will run the thread, more than one time).[/quote]I think you don't need to create more threads -- you just need asynchronous, object-oriented, event-driven programming.

                  You can re-use QNetworkAccessManager, and call manager->post() over and over again. If you use signals and slots, your GUI should still be free.

                  [quote]I am wondering why the same code working without threads and not with threads.

                  ...

                  During this process I need the program GUI user interface free for other things.[/quote]When you used code without threads, did your GUI freeze or lag?

                  [quote author="Zain" date="1350645720"]now the replyFinish slot(finished signal) is not working (it never get called) [/quote]Your slot was never called because your signal was never emitted, because your thread didn't have an event loop, because NewThread::run() did not call exec()

                  More questions: What does your post data contain?

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

                  1 Reply Last reply
                  0
                  • Z Offline
                    Z Offline
                    Zain
                    wrote on last edited by
                    #9

                    Thanks for the replies,

                    @JKSH

                    The postdata contains some values of the form...some check box and radio buttons true /false and few textbox values..for different values the url gives different data.

                    Your eventLoop suggestion get the reply finished called. But it is of no use when I execute the thread again.(I have tried the exit,, quit and again start and execute with so many combinations).

                    Now I am thinking that it is not possible to use the QNetworkAccessManger in thread it is already asynchronous.. so Now I will use it directly without threads..
                    ...please share if you get any Idea to execute a single thread with qNetworkAccessManager in loop (it is an indirect recursion in my case)

                    Thank you all for your efforts....I am leaving the thought of using QNetworkAccessManager in threads.

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

                      Here's an example. I can fill in the form 100 times, and download 100 different websites, while using the same QNetworkAccessManager.

                      @
                      class ProgramCore : public QObject
                      {
                      private:
                      Q_OBJECT

                      MainWindow            *gui;
                      QNetworkAccessManager *manager;
                      

                      private slots:
                      void getPage() const
                      {
                      QNetworkRequest req;
                      req.setUrl(QUrl("My url"));

                          QByteArray postData = gui->readFormData();
                      
                          // Connect the signal from the reply, not from the manager.
                          // The QNetworkReply will download data in the background. Your GUI is free
                          // during this time.
                          QNetworkReply *reply = manager->post(req, postData);
                          connect(reply, SIGNAL(finished()), this, SLOT(processReply()));
                      }
                      
                      void processReply() const
                      {
                          // Use QObject::sender() to find the object that emitted the signal
                          QNetworkReply *reply = qobject_cast<QNetworkReply*>(this->sender());
                      
                          QString answer = QString::fromUtf8(reply->readAll());
                          qDebug () << answer;
                      
                          // Make sure you don't have a memory leak! Delete the object when you've finished
                          reply->deleteLater();        
                      }
                      

                      public:
                      ProgramCore(QObject *parent = 0) : QObject(parent)
                      {
                      this->gui = new MainWindow(this);
                      this->manager = new QNetworkAccessManager(this);

                          connect(gui, SIGNAL(userSubmittedTheForm()), this, SLOT(getPage()));
                      }
                      

                      }
                      @

                      Final notes: This is just Repetition, not "Indirect Recursion". You only wanted to repeat a task, so you shouldn't use threads to do that. Threads are for Parallel Processing -- for example, making 2 CPU cores process different data at the same time.

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

                      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