Andrew Li
Andrew Li

Reputation: 1055

Could one thread get the signal from the other one in the qt?

I don't have the deep knowledge about QT thread.
I am gonna QT app that has the background thread.
The background thread is executed in the other thread different to the main one.
In the background thread, this makes new thread for calling the api by using signal-slot mechanism.
For example.

 //BackThread.h
 {
     Q_OBJECT
   public:
     BackThread(){
         thread = new QThread; moveToThread(thread);
         connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
         connect(thread, SIGNAL(finished()), this, SLOT(deleteLater()));
     }

    public slots:
     void start(){ thread->start();}
     void terminate(){thread->quit(); }
     void on_readyResult(QNewtworkReply* reply){ // process response}
     void dowork(){
        //This is called by signal 'signal_dowork()'
        APIManager * manager = new APIManager;
        connect(manager, SIGNAL(readyResult(QNetworkReply*)), this, SLOT(on_readyResult(QNeworkReply*)));
        connect(this, SIGNAL(signal_callAPI(QString)), manager, SLOT(callAPI(QString)));
        connect(manager, SIGNAL(readyResult(QNetworkReply*)), manager, SLOT(terminate()));  //Here api call is needed only one time.
        manager->start();
        while(true){
           QThread::sleep(20);
           emit signal_callAPI("http://url.com");
        }
     }
    signals: 
        signal_callAPI(QString);
    private:
      QThread *thread;
 }

 //APIManager.h
 {
 Q_OBJECT
  public:
 APIManager(){
     thread = new QThread; moveToThread(thread);
     connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
     connect(thread, SIGNAL(finished()), this, SLOT(deleteLater()));
 }

 callAPI(QString api){
     QNetworkAccessManager *manager;
     manager = new QNetworkAccessManager();
     // Send web request by this QNewtorkAccessManager ....
     //...
     connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(on_readyReply(QNetworkReply*)));
 }
public slots:
 void start(){ thread->start();}
 void terminate(){thread->quit(); }
 void on_readyReply(QNewtworkReply* reply){ 
    //This is called by the signal 'finished(QNetworkReply*)' of the QNetworkAccessManager, so the readyResult signal is emitted.
    emit readyResult(reply);  //this signal is emitted,but the connected slot 'on_readyResult' is not fired whenever.
 }
signals: 
    readyResult(QString);
private:
  QThread *thread;
}

 //MainApp.cpp
    BackThread * backthread = new BackThread;
    connect(this, SIGNAL(signal_dowork()), backthread, SLOT(dowork()));
    backthread->start();
    emit signal_dowork();  //This calls dowork() slot.

As you could see, the main app starts the background thread and emits the signal for the background thread to do something. (signal_dowork())
This calls dowork() slot of the BackThread Object.
In this BackThread Object, this starts new Thread to call the api.
BackThread and APIManager thread are different.
APIManager class sends the web request and receives the reply using signal-slot.
When receiving the signal ,finished(QNetworkReply*) of the QNewtworkAccessManager, in the APIManager, the slot , on_readyReply(QNetworkReply*) , emits the signal again for the BackThread to process this reply.
But the BackThread doesn't receive this signal whenever.
In the QT document, it is described that

Auto Connection (default) If the signal is emitted in the thread which the receiving object has affinity then the behavior is the same as the Direct Connection. Otherwise, the behavior is the same as the Queued Connection.
Queued Connection The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.

Though the APIManager emits the signal readyResult(reply); and this signal is connected to the slot on_readyResult(QNetworkReply*), that slot is not called.
Is it caused becuase BackThread and APIManager are executed in the different threads?
And then how could the app connects the signal and slots of the different threads?
Please explain me why this happens.
Thanks

Upvotes: 1

Views: 357

Answers (1)

Talent Developer
Talent Developer

Reputation: 142

I've found the issue in your code.
If the QOjbect is moved to the thread, they have different Event Loop. Your dowork() function have the infinite loop.
So this blocks the Event Loop of the backthread.
So it couldn't get any signal from the other thread.
You have not to use the infinite loop in the slot of the QOjbect it blocks the Event Loop.

  void dowork(){
    //This is called by signal 'signal_dowork()'
    APIManager * manager = new APIManager;
    connect(manager, SIGNAL(readyResult(QNetworkReply*)), this, SLOT(on_readyResult(QNeworkReply*)));
    connect(this, SIGNAL(signal_callAPI(QString)), manager, SLOT(callAPI(QString)));
    connect(manager, SIGNAL(readyResult(QNetworkReply*)), manager, SLOT(terminate()));  //Here api call is needed only one time.
    manager->start();
    while(true){  //This blocks the event loop. Event Loop couldn't get any signal from the other thread.
       QThread::sleep(20);
       emit signal_callAPI("http://url.com");
    }
 }

Without while command, that works smoothly. Hope this will help you.

Upvotes: 2

Related Questions