簡體   English   中英

來自主線程的信號未到達第二線程Qt 5中的插槽

[英]Signal from Main Thread not reaching slot in Second Thread Qt 5

我正在編寫一個程序,每REFRESH_RATE毫秒捕獲一次來自相機的圖像,然后將其發送到某種計算算法。 我決定使用QThread來確定該算法的啟動時間,但是該算法正在主線程上運行,因為我需要在此之前創建對象。 無論如何,這很好。 當我嘗試關閉第二個線程時,麻煩就開始了。這是代碼。

相機:

class Camera : public QMainWindow
{
    Q_OBJECT

    public:
        Camera(QWidget *parent = 0){

             AlgoQThread = new QThread;
             myAlgoThreadWorker = new AlgoThreadWorker( (Camera *) this );
             myAlgoThreadWorker->moveToThread(AlgoQThread);

             //Launch The thread
             connect(AlgoQThread, SIGNAL(started()), myAlgoThreadWorker, SLOT(process())); 

             connect(myAlgoThreadWorker, SIGNAL(finished()), AlgoQThread, SLOT(quit())); 
             // The line meant to stop the thread at next loop
             connect(this, SIGNAL(stopAlgoThread()), myAlgoThreadWorker, SLOT(stopThread()));

             connect(myAlgoThreadWorker, SIGNAL(finished()), myAlgoThreadWorker, SLOT(deleteLater()));
             connect(AlgoQThread, SIGNAL(finished()), AlgoQThread, SLOT(deleteLater()));

             AlgoQThread->start();
         }

     private slots:
         void errorString(QString error);

         //This function is triggered by a signal sent by the method called in AlgoThreadWoker::process()
         void some_algorithm(){
             ...
             emit stopAlgoThread();
         }

     signals:
         void stopAlgoThread();

     private:
         QThread * AlgoQThread;
         AlgoThreadWorker * myAlgoThreadWorker;
};

algoThreadWorker:

class AlgoThreadWorker : public QObject
{
    Q_OBJECT

    public:
        AlgoThreadWorker(Camera * context){
            parentCamera = context;
        }
        Camera* parentCamera;

    public slots:
        void process(){
            while(1){

                QMutexLocker locker(&m_mutex);
                if (t_stop) break;

                parentCamera->isCapturingImage = true;

                //This triggers the some_algorithm() using a signal sent by imageCapture from main Thread
                parentCamera->imageCapture->capture();

                //Wait REFRESH_RATE millisecondes
                Sleep(REFRESH_RATE);

            }

            //Ends the thread
            emit finished();
        }

    private slots:
        void stopThread(){
            QMutexLocker locker(&m_mutex);
            t_stop = true;
        };

    signals:
        void finished();
        void error(QString);

    private:
        bool t_stop;
        QMutex m_mutex;
    };

而且,正如您可能已經預見到的那樣,它是行不通的。 我可以some_algorithm()啟動some_algorithm() ,但無法結束線程。 stopThread()插槽甚至沒有啟動,我已經測試過了。

由於您在while循環中忙於等待,因此事件循環永遠不會有機會處理接收到的信號。

qApp->processEvents()將控制權交給事件循環,以便處理等待的作業。

請注意,通常您不必自己調用它,Qt會為您調用它。 在您的情況下,這是必要的,因為您有一個無限循環,這會阻止Qt執行其工作。

解決方案:

void process(){

    while(1){
        qApp->processEvents();
        ^^^^^^^^^^^^^^^^^^^^^^

        .....
    }

    //Ends the thread
    emit finished();
}

stopThread()是私有的,因此只能從AlgoThreadWorker訪問。

Qt的事件循環已經提供了安全的跨線程插槽調用和事件傳遞。 您的錯誤主要與錯誤地重新實現Qt已經提供的功能有關:

  1. 事情已經是線程安全的。 放下互斥鎖。

  2. thread->quit()有效,並且將從給定線程中運行的事件循環退出。 QThread ,線程將完成。

  3. 不要無緣無故地使代碼不可移植( Sleep是特定於Windows的)。 如果您希望定期執行操作,只需運行一個計時器( QBasicTimerQTimer )。

此答案提供了完整的示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM