一種使用QThread線程的新方法QObject::moveToThread

sydnash的專欄

昨晚在一個郵件列表裏面看見一個關於在線程種使用signal/slot的討論,由於回覆太多,這裏就不貼出原文了。

        主要是關於怎樣從一個線程發送信號到另外一個線程的問題。其實這個也不是什麼複雜的問題,在qt的asstant裏面已經描訴的比較清楚了。當我們鏈接信號的時候使用qt::queuedConnection就能使slot在它自己的線程裏面運行。

        另我驚訝的是在其中一個的回覆種他給出了一些資料,其中一個名爲you‘ar doing it wrong。帖子是英文的,由於英文水平有限,加上他所說的使用QT thread的方式和我們平時直接派生QThread實現run函數的方式不一樣,所以讓我看的非常含糊,甚至到了不清不楚的地步。看了後面的大量的回覆和討論,勉強明白了它的意思。

    具體請看這裏
http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/

       在那裏他提出了一種新的使用QThread的方式,其實也不算是信了,據說qt 4.4就已經有了。那就是QObject::moveToThread。根據QT的asstant的描述,moveToThread的作用是把一個QOject移動到一個線程裏面去,那麼它到底是什麼意思呢。我的理解就是當我們調用QObject的moveToThread方法之後,我們這個派生自QObject的類的代碼就會在新的線程裏面執行。而那篇文章所說的就是大多數對這個函數產生了誤解,人們總是在派生的QThread的類的構造函數裏面調用moveToThread(this)以希望把該類的所有函數都在該線程裏面執行。這樣是錯誤的。

         今天爲了驗證這個方法到底有什麼用,寫了一些代碼來做測試。

1、

   

  1. #include <QObject>  
  2. #include <QDebug>  
  3. #include <QThread>  
  4.   
  5. class MyObject : public QObject {  
  6.     Q_OBJECT  
  7.     public:  
  8.         MyObject() {};  
  9.         ~MyObject() {}  
  10.   
  11.     public slots:  
  12.         void first() {  
  13.             qDebug() << QThread::currentThreadId();  
  14.         }  
  15.         void second() {  
  16.             qDebug() << QThread::currentThreadId();  
  17.         }  
  18.         void three() {  
  19.             qDebug() << QThread::currentThreadId();  
  20.         }  
  21. };  

2、mainwindow.cxx

  1. #include "mainwindow.h"  
  2. #include <QPushButton>  
  3. #include <QVBoxLayout>  
  4. #include "myobject.h"  
  5.   
  6. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {  
  7.     my = new MyObject;  
  8.     firstButton = new QPushButton(tr("first"), 0);  
  9.     connect(firstButton, SIGNAL(clicked()), my, SLOT(first()), Qt::QueuedConnection);  
  10.     secondButton = new QPushButton(tr("second"), 0);  
  11.     connect(secondButton, SIGNAL(clicked()), my, SLOT(second()), Qt::QueuedConnection);  
  12.     threeButton = new QPushButton(tr("three"), 0);  
  13.     connect(threeButton, SIGNAL(clicked()), my, SLOT(three()), Qt::QueuedConnection);  
  14.     selfButton = new QPushButton(tr("self"), 0);  
  15.     connect(selfButton, SIGNAL(clicked()), this, SLOT(onSelfPushed()));  
  16.     exitButton = new QPushButton(tr("exit"), 0);  
  17.     connect(exitButton, SIGNAL(clicked()), this, SLOT(onExitPushed()));  
  18.   
  19.     QVBoxLayout *layout = new QVBoxLayout;  
  20.     layout->addWidget(firstButton);  
  21.     layout->addWidget(secondButton);  
  22.     layout->addWidget(threeButton);  
  23.     layout->addWidget(selfButton);  
  24.     layout->addWidget(exitButton);  
  25.   
  26.     QWidget *p = new QWidget;  
  27.     p->setLayout(layout);  
  28.   
  29.     QThread *thread = new QThread;  
  30.     my->moveToThread(thread);  
  31.   
  32.     thread->start();  
  33.     connect(thread, SIGNAL(started()), my, SLOT(first()));  
  34.   
  35.     setCentralWidget(p);  
  36. }  
  37.   
  38. MainWindow::~MainWindow() {  
  39. }  
  40.   
  41. void MainWindow::onFirstPushed() {  
  42.     my->first();  
  43. }  
  44.   
  45. void MainWindow::onSecondPushed() {  
  46.     my->second();  
  47. }  
  48.   
  49. void MainWindow::onThreePushed() {  
  50.     my->three();  
  51. }  
  52.   
  53. void MainWindow::onSelfPushed() {  
  54.     qDebug() << QThread::currentThreadId();  
  55. }  
  56.   
  57. void MainWindow::onExitPushed() {  
  58.     close();  
  59. }  

    通過測試,在mainwidow.cxx使用上面的代碼的時候,由於my調用了movetothread函數,那麼它所有的槽函數都是執行在新開闢的線程裏面。

   如果去掉moveToThread函數,那麼所有的函數都將執行在gui線程裏面。

   同時爲了測試connect的第五個參數,在connect的時候可以將Qt::QueuedConnection修改爲Qt::DirectConnection,這樣所有的槽函數也將在主線程裏面執行。

     最後要注意的是,如果上面connect的時候連接的是this的onXXXXXX槽函數再來調用的my的槽函數的話,那麼這些槽函數也將執行在onXXXXX槽函數所在的線程,這裏是主線程。

     通過上面的測試,我們在使用線程的時候,就可以將一個類派生自QObject,然後實現所有的signal/slot,然後通過調用movetothread函數來使他們執行在新的線程裏面,而不是每次都要重新派生QThread,並且派生QThread函數的另外一個不好的地方是隻有run函數內部的代碼纔會執行在新線程裏面,相比起來,派生QObject並使用movetothread函數更具有靈活性。

    最後,把討論中列出的所有的網址列出來哈。

http://qt-project.org/doc/qt-4.8/thread-basics.html
http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/
http://qt-project.org/wiki/Threads_Events_QObjects
http://qt-project.org/wiki/QThreads_general_usage
http://labs.qt.nokia.com/2006/12/04/threading-without-the-headache/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章