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