問題描述:界面線程MainApp爲主線程,工作線程MyThread爲一子線程,從工作線程向主線程傳遞字符串用於在主線程中顯示。
Qt的信號與槽機制可以將任何繼承自QObject類的對象捆綁在一起,使不同對象之間能夠相互通信。
成功的實現:
工作線程:
class MyThread:public QThread
{
Q_OBJECT
...
signals:
void MsgSignal(const QString&
tep);//用於向主線程傳遞字符串
protected:
void run();//run 中的內容纔是子線程中執行的內容!
}
void MyThread::run()
{
Sleep(3000);//頭文件:windows.h
QString tep("mou-mou-mou");
emit MsgSignal(tep);
Sleep(3000);//各個Sleep的位置可放置具體執行的工作
}
主線程:
class MainApp:public QWidget
{
Q_OBJECT
...
public:
MainApp();
...
private slots:
void OnMsgSignal(const QString& tep2);//接受子線程傳遞字符串用於顯示
private:
MyThread* m_thread;
}
MainApp::MainApp()
{
...
m_thread= new MyThread();
connect(m_thread, SIGNAL(MsgSignal(const QString&)),
this, SLOT(OnMsgSignal(const QString&)));//此處connect的第五個參數默認變成Qt::QueuedConnection
m_thread->start();
}
void MainApp::OnMsgSignal(const QString& tep2)
{
//使用子線程傳遞來的tep2
}
實現過程中遇到過的問題:
1.connect函數的第五個參數代表信號與槽的連接模式,線程間的信號與槽不能使用Qt::DirectConnection直接連接方式,因爲它要求在發信號的線程內執行槽函數。而Qt::QueuedConnection隊列方式將信號轉換成事件發送到槽函數所在線程的消息隊列中讓槽函數所在線程來處理,可以實現線程安全的線程間的通信。這樣的時效性也不差,上面的實現中,會在子線程“run()”函數中的第二個Sleep之前執行主線程的“OnMsgSignal(constQString& tep2)”。
於是在調試的時候子線程的“emit MsgSignal(const QString& tep);”的下一步並不會立即跳轉到主線程的“OnMsgSignal(const QString& tep2)”,我開始還以爲信號中途丟了沒送達呢。。而強制使用Qt::DirectConnection模式卻怎麼也擺脫不了錯誤。
2.線程間用“信號與槽”傳遞引用參數的話,一定要加const,因爲const文字常量存在常量區中,生命週期與程序一樣的長。這樣可以避免slot調用的時候參數的運行期已過而使引用無效。
我開始沒注意到需要加const,程序運行時並沒有報告錯誤,但是主線程毫無使用子線程傳遞來的字符串的跡象,這讓我更加錯誤地以爲子線程發送的信號丟了。。
想不清楚的問題總算是解決了,前幾天憤怒抓狂的“我”們,你們可以安心休息啦讓我沿着你們沒有走完的路繼續前行吧!