来自主线程的信号没有到达第二线程qt5的插槽

Signal from Main Thread not reaching slot in Second Thread Qt 5

本文关键字:线程 插槽 qt5 信号      更新时间:2023-10-16

我正在编写一个程序,每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()没有问题,但我不能结束线程。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)。

这个答案提供了一个完整的例子