繁体   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