除了信號觸發線程與接收者線程相同的情況能直接調用到slot,其它情況都依賴事件機制(解決上面代碼收不到信號的問題其實很簡單,在線程的run();函數中添加一個事件循環就可以了,即加入一句exec();)
阿新 • • 發佈:2018-08-28
使用 usleep tle 結果 線程 方法 params str signal
- MainWindow::MainWindow(QWidget *parent) :
- QMainWindow(parent)
- {
- pThreadCon = new CSerialThread();
- pThreadCon->start();
- m_pTimer = new QTimer();
- connect(m_pTimer,SIGNAL(timeout()),SLOT(onTimer()));
-
m_pTimer->start(1000);
- }
- void MainWindow::onTimer()
- {
- m_pTimer->stop();
- connect(this,SIGNAL(onSignal()),g_pThread,SLOT(onTimer()),Qt::QueuedConnection);
- emit onSignal();
- this->disconnect();
- }
- void CSerialThread::run()
- {
- g_pThread = new CThread();
- }
- CThread::CThread(QObject *parent) :
- QThread(parent)
- {
- }
- void CThread::onTimer()
- {
- sleep(5);
- qDebug("------onTimer call");
- }
只添加了部分代碼,運行這個程序是看不到打印信息的,說明這個信號沒有接收到,如果將connect最後一個參數改成直接連接,會有打印,但是主界面會卡住5秒。一直被這個問題困擾,為什麽g_pThread 收不到信號呢,首先應該知道,Qt的信號和槽是基於事件循環的,就像main函數最後都會有一句 return exec();這裏就啟動了事件循環,除了信號觸發線程與接收者線程相同的情況能直接調用到slot,其它情況都依賴事件機制。QThread::run()實際上是簡單調用了QThread::exec(),而它啟動了線程的事件循環,但是run()函數結束後,事件循環結束了,這個時候我們再發送信號,沒有事件循環的支持,g_pThread就收不到信號了。
QThread的內部結構非常有趣:
- QThread並不生存於執行run()的新線程內。它生存於舊線程中。
- QThread的大多數成員方法是線程的控制接口,並設計成從舊線程中被調用。不要使用moveToThread()將該接口移動到新創建的線程中;調用moveToThread(this)被視為不好的實踐。
- exec()和靜態方法usleep()、msleep()、sleep()要在新創建的線程中調用。
- QThread子類中定義的其他成員可在兩個線程中訪問。開發人員負責訪問的控制。一個典型的策略是在start()被調用前設置成員變量。一旦工作線程開始運行,主線程不應該操作其他成員。當工作線程終止後,主線程可以再次訪問其他成員。這是一個在線程開始前傳遞參數並在結束後收集結果的便捷的策略。
QObject必須始終和parent在同一個線程。
所以解決上面代碼收不到信號的問題其實很簡單,在線程的run();函數中添加一個事件循環就可以了,即加入一句exec();
有不對的地方希望大家指正,相互學習。
https://blog.csdn.net/sddsighhz/article/details/36894247
成都-陳劍客
信號槽不就是一個回調函數嘛
他啥也不依賴
你可以這麽幹
取得函數地址
然後把這個地址設置到emit的地方
效果和信號槽一模一樣
除了信號觸發線程與接收者線程相同的情況能直接調用到slot,其它情況都依賴事件機制(解決上面代碼收不到信號的問題其實很簡單,在線程的run();函數中添加一個事件循環就可以了,即加入一句exec();)