[英]Qt Signal calling from second thread works -> no effect on connected slot
[英]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已經提供的功能有關:
事情已經是線程安全的。 放下互斥鎖。
thread->quit()
有效,並且將從給定線程中運行的事件循環退出。 在QThread
,線程將完成。
不要無緣無故地使代碼不可移植( Sleep
是特定於Windows的)。 如果您希望定期執行操作,只需運行一個計時器( QBasicTimer
或QTimer
)。
此答案提供了完整的示例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.