1. 程式人生 > >除了信號觸發線程與接收者線程相同的情況能直接調用到slot,其它情況都依賴事件機制(解決上面代碼收不到信號的問題其實很簡單,在線程的run();函數中添加一個事件循環就可以了,即加入一句exec();)

除了信號觸發線程與接收者線程相同的情況能直接調用到slot,其它情況都依賴事件機制(解決上面代碼收不到信號的問題其實很簡單,在線程的run();函數中添加一個事件循環就可以了,即加入一句exec();)

使用 usleep tle 結果 線程 方法 params str signal

  1. MainWindow::MainWindow(QWidget *parent) :
  2. QMainWindow(parent)
  3. {
  4. pThreadCon = new CSerialThread();
  5. pThreadCon->start();
  6. m_pTimer = new QTimer();
  7. connect(m_pTimer,SIGNAL(timeout()),SLOT(onTimer()));
  8. m_pTimer->start(1000);
  9. }
  10. void MainWindow::onTimer()
  11. {
  12. m_pTimer->stop();
  13. connect(this,SIGNAL(onSignal()),g_pThread,SLOT(onTimer()),Qt::QueuedConnection);
  14. emit onSignal();
  15. this->disconnect();
  16. }
  17. void CSerialThread::run()
  18. {
  19. g_pThread = new CThread();
  20. }
  21. CThread::CThread(QObject *parent) :
  22. QThread(parent)
  23. {
  24. }
  25. void CThread::onTimer()
  26. {
  27. sleep(5);
  28. qDebug("------onTimer call");
  29. }

只添加了部分代碼,運行這個程序是看不到打印信息的,說明這個信號沒有接收到,如果將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();)