Qt多線程學習-用例子來理解多線程

來源:互聯網
上載者:User

 

01 class MThread :public QThread  

02 {  

03 public:  

04     MThread();  

05     ~MThread();  

06     void run();  

07     void foo();  

08     ...  

09        

10 };
 

POINT 1:QThread類的執行個體與普通類的執行個體沒什麼不同,只是運行著的run()函數會不同

例1:

顯示代碼列印
01 class MDialog :public QDialog  

02 {  

03     ...  

04     MThread *mythread;  

05 };  

06 MDialog::MDialog()  

07 {  

08     mythread = new MThread;  

09     ...   

10 }

需要注意的是,在QT中,QThread對象的執行個體mythread是屬於建立它的線程(線程A,即MDialog所在的線程)的,mythread的所有程式碼與資料都放在與MDialog相同的空間中.這時的mythread,就像任何普通的自己定義的類的執行個體一樣.但是在調用mythread->start()之後,mythread的run()函數中的代碼會在新的線程(線程B)中執行.在run()函數中聲明的變數\執行個體化的對象,都屬於線程B.但是mythread的所有代碼,都還在儲存線上程A中,只是run()函數的"執行"是線上程B中.

在MDialog中,使用

 

1.mythread->foo();
foo()是線上程A中執行的.

 

在MDialog中使用

 

1.顯示代碼列印
1 connect(this, SIGNAL(sigDialogSignal()), mythread, SLOT(slotThreadSlot()));
當emit sigDialogSignal()時,是會在MDialog所在的線程A中執行的.因為mythread與MDialog同屬於一個線程, 這時thread可以看做一個普通類的執行個體.另外,因為connect函數的串連方式預設是自動連接,而對同屬於一個純種的兩個對象,自動連接會使用直接連接,即slot在發出signal的線程中立即執行.

 

例2:

 

 

顯示代碼列印
01 #include "mthread.h"  

02 #include <QDebug>  

03 MThread::MThread(QObject *parent)  

04     : QThread(parent)  

05 {  

06     myTimer.start(1);  

07     connect(&myTimer, SIGNAL(timeout()), this, SLOT(slotPrint()));  

08 }  

09   

10 MThread::~MThread()  

11 {  

12   

13 }  

14   

15 void MThread::run()  

16 {     

17     for (int i = 0; i < 100; ++i) {  

18         for (int j = 0 ; j < 10000; ++j) {  

19             qDebug()<<"---------"<<i;  

20         }  

21     }  

22     exec();  

23 }  

24   

25 void MThread::slotPrint()  

26 {  

27     qDebug()<<"==============================";  

28   

29 }
 

 

 

運行後出現:

 

1....
2....
3.---------9
4.==============================================================
5.---------9
6....
7....
不能誤以為:在一個QThread類的衍生類別中,run()函數中的語句在運行時,可能被本線程定時器逾時slot中斷. (錯誤)

事實上,slotPrint()在建立MThread的執行個體的線程中執行.

 

POINT 2:線程B中的對象要想接收線程A中的對象發來的signal, 必須進入exec(), 如在exec()前有死迴圈, 沒有進入exec(), 則線程B中的對象不會收到signal.

 

 

顯示代碼列印
1 void MThread::run()  

2 {  

3     while(1) {  

4         dosomething();  //此迴圈永不退出  

5     }  

6     exec();             //如果此事件迴圈不能進入,剛此線程不會收到任何signal  

7 }
 

 

POINT 3:線程A中的指標可指向線程B中建立的對象執行個體,  這個執行個體屬於線程B. 指標僅僅是一個地址, 而對象執行個體的變數/代碼等都屬於線程B.

例1:

顯示代碼列印
01 class MThread : public QThread  

02 {  

03     Q_OBJECT  

04   

05 public:  

06     MThread(QObject *parent = 0);  

07     ~MThread();  

08     void run();  

09     MPrint *mprint;  

10 };  

11 void MThread::run()  

12 {  

13     mprint = new MPrint;  

14     exec();  

15 }  

16 //如此聲明,mprint所指向的對象屬於另一個線程.
 

 

例2:

顯示代碼列印
01 class MThread : public QThread  

02 {  

03     Q_OBJECT  

04   

05 public:  

06     MThread(QObject *parent = 0);  

07     ~MThread();  

08     void run();  

09     MPrint *mprint;  

10 private:  

11     QTimer *myTimer;  

12   

13   

14 private slots:  

15     void slotPrint();     

16     void testFoo();  

17 };  

18   

19 void MThread::run()  

20 {  

21     myTimer = new QTimer;  

22     mprint = new MPrint;  

23     myTimer->setInterval(100);  

24     connect(myTimer, SIGNAL(timeout()), this, SLOT(testFoo()), Qt::DirectConnection);  

25     QTimer::singleShot(0, myTimer,SLOT(start()));  

26     exec();  

27 }
 

 

以上這樣寫run(),myTimer在run()中new,即myTimer這個指標屬於舊線程,但myTimer所指向的QTimer執行個體的實體在新的線程中,testFoo()會在新線程中執行.

例3:

顯示代碼列印
01 void MThread::run()  

02 {  

03     QTimer myTimer;  

04     mprint = new MPrint;  

05     myTimer.setInterval(100);  

06     connect(&myTimer, SIGNAL(timeout()), this, SLOT(testFoo()), Qt::DirectConnection);  

07     QTimer::singleShot(0, &myTimer,SLOT(start()));  

08     //testFoo();  

09     exec();  

10 }
 

 

以上這樣寫run(),myTimer在run()中聲明,即myTimer屬於新的線程,testFoo()也會在新線程中執行.

例4:

顯示代碼列印
01 class MThread : public QThread  

02 {  

03     Q_OBJECT  

04   

05 public:  

06     MThread(QObject *parent = 0);  

07     ~MThread();  

08     void run();  

09     MPrint *mprint;  

10 private:  

11     QTimer myTimer;  

12   

13   

14 private slots:  

15     void slotPrint();     

16     void testFoo();  

17 };  

18   

19   

20 void MThread::run()  

21 {  

22     mprint = new MPrint;  

23     myTimer.setInterval(100);  

24     connect(&myTimer, SIGNAL(timeout()), this, SLOT(testFoo()));  

25     QTimer::singleShot(0, &myTimer,SLOT(start()));  

26     //testFoo();  

27     exec();  

28 }
 

 

以上這樣寫run(),testFoo()會在建立myTimer的老線程中執行.因為可以看到,mytimer和this(即mythread),都是在同一個線程中,只是在另一個線程中(run()),做了connect操作.

要注意的是,線上程B中啟動線程A中的一個定時器,不能使用myTimer.start(),這樣啟動不了定時器.而應使用signal來觸發start()這個slot.

 

POINT 5:slot不會中斷同線程中的slot.

例1:

顯示代碼列印
01 #include "mthread.h"  

02 #include <QDebug>  

03 MThread::MThread(QObject *parent)  

04     : QThread(parent)  

05 {  

06     myTimer.start(1);  

07     connect(&myTimer, SIGNAL(timeout()), this, SLOT(slotPrint()));  

08 }  

09   

10 MThread::~MThread()  

11 {  

12   

13 }  

14   

15 void MThread::run()  

16 {  

17     exec();  

18 }  

19   

20 void MThread::slotPrint()  

21 {  

22     qDebug()<<"===========================";  

23     for (int i = 0; i < 100; ++i) {  

24         for (int j = 0 ; j < 10000; ++j) {  

25             qDebug()<<"---------"<<i;  

26         }  

27     }  

28 }
 

 

slotPrint()函數運行完之後才會退出,說明slot不會中斷slot,一個slot在執行完之後才會執行下一個slot.

注意:slotPrint()在建立MThread執行個體的線程中執行.而不是使用thread->start()建立出的那個線程.

例2:

顯示代碼列印
01 #include "mthread.h"  

02 #include <QDebug>  

03 MThread::MThread(QObject *parent)  

04     : QThread(parent)  

05 {  

06     myTimer.start(1);  

07     connect(&myTimer, SIGNAL(timeout()), this, SLOT(slotPrint()));  

08 }  

09   

10 MThread::~MThread()  

11 {  

12   

13 }  

14   

15 void MThread::run()  

16 {  

17     testFoo();  

18     exec();  

19 }  

20   

21 void MThread::slotPrint()  

22 {  

23     qDebug()<<"=======================";  

24   

25 }  

26   

27 void MThread::testFoo()  

28 {  

29     for (int i = 0; i < 100; ++i) {  

30         for (int j = 0 ; j < 10000; ++j) {  

31             qDebug()<<"---------"<<i;  

32         }  

33     }  

34 }
 

 

以上代碼中,slotPrint()與testFoo()會在兩個不同的線程中執行.

文章出處:飛諾網(www.diybl.com):http://www.diybl.com/course/3_program/c/c_js/20090303/157373.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.