一个线程能否从 qt 中的另一个线程获取信号?

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

我对QT线程了解不深
我要使用具有后台线程的 QT 应用程序。
后台线程在不同于主线程的另一个线程中执行。
在后台线程中,这会创建新的线程来使用信号槽机制调用 api。
例如。

 //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.

如您所见,主应用程序启动后台线程并发出信号让后台线程执行某些操作。 (signal_dowork())
这会调用 BackThread 对象的 dowork() 槽。
在这个 BackThread 对象中,这将启动新线程来调用 api.
BackThread 和 APIManager 线程不同。
APIManager class 发送网络请求并使用信号槽接收回复。
当接收到 QNewtworkAccessManager 的信号 finished(QNetworkReply*) 时,在 APIManager 中,插槽 on_readyReply(QNetworkReply*) 再次发出信号,以便 BackThread 处理此回复。
但是 BackThread 并没有在任何时候接收到这个信号。
QT document中描述的是

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.

尽管 APIManager 发出信号 readyResult(reply); 并且此信号连接到插槽 on_readyResult(QNetworkReply*),但未调用该插槽。
是因为BackThread和APIManager在不同的线程执行造成的吗?
那么应用程序如何连接不同线程的信号和插槽?
请解释为什么会这样。
谢谢

我在您的代码中发现了问题。
如果将 QOjbect 移到线程中,它们将具有不同的 Event Loop。 你的 dowork() 函数有无限循环。
所以这会阻塞 backthread.
的事件循环 所以它无法从其他线程获得任何信号。
您不必在 QOjbect 的插槽中使用无限循环,它会阻塞事件循环。

  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");
    }
 }

没有while命令,工作顺利。 希望这会帮助你。