理解Qt多线程类
来源:互联网 发布:智库研究员 知乎 编辑:程序博客网 时间:2024/04/28 10:40
例1:
1.class MThread :public QThread
2.{
3.public:
4. MThread();
5. ~MThread();
6. void run();
7. void foo();
8. ...
9.
10.};
1.class MDialog :public QDialog
2.{
3. ...
4. MThread *mythread;
5.};
6.MDialog::MDialog()
7.{
8. mythread = new MThread;
9. ...
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.connect(this, SIGNAL(sigDialogSignal()), mythread, SLOT(slotThreadSlot()));
当emit sigDialogSignal()时,是会在MDialog所在的线程A中执行的.因为mythread与MDialog同属于一个线程, 这时thread可以看做一个普通类的实例.另外,因为connect函数的连接方式默认是自动连接,而对同属于一个纯种的两个对象,自动连接会使用直接连接,即slot在发出signal的线程中立即执行.
例2:
1.#include "mthread.h" 2.#include <QDebug> 3.MThread::MThread(QObject *parent)
4. : QThread(parent)
5.{
6. myTimer.start(1);
7. connect(&myTimer, SIGNAL(timeout()), this, SLOT(slotPrint()));
8.}
9.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:
1.class MThread : public QThread
2.{
3. Q_OBJECT
4.5.public:
6. MThread(QObject *parent = 0);
7. ~MThread();
8. void run();
9. MPrint *mprint;
10.};
11.void MThread::run()
12.{
13. mprint = new MPrint;
14. exec();
15.}
16.//如此声明,mprint所指向的对象属于另一个线程.例2:
1.class MThread : public QThread
2.{
3. Q_OBJECT
4.5.public:
6. MThread(QObject *parent = 0);
7. ~MThread();
8. void run();
9. 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:
1.void MThread::run()
2.{
3. QTimer myTimer;
4. mprint = new MPrint;
5. myTimer.setInterval(100);
6. connect(&myTimer, SIGNAL(timeout()), this, SLOT(testFoo()), Qt::DirectConnection);
7. QTimer::singleShot(0, &myTimer,SLOT(start()));
8. //testFoo(); 9. exec();
10.}
以上这样写run(),myTimer在run()中声明,即myTimer属于新的线程,testFoo()也会在新线程中执行.
例4:
1.class MThread : public QThread
2.{
3. Q_OBJECT
4.5.public:
6. MThread(QObject *parent = 0);
7. ~MThread();
8. void run();
9. 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:
1.#include "mthread.h" 2.#include <QDebug> 3.MThread::MThread(QObject *parent)
4. : QThread(parent)
5.{
6. myTimer.start(1);
7. connect(&myTimer, SIGNAL(timeout()), this, SLOT(slotPrint()));
8.}
9.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.}
29.slotPrint()函数运行完之后才会退出,说明slot不会中断slot,一个slot在执行完之后才会执行下一个slot.
注意:slotPrint()在创建MThread实例的线程中执行.而不是使用thread->start()创建出的那个线程.
例2:
1.#include "mthread.h" 2.#include <QDebug> 3.MThread::MThread(QObject *parent)
4. : QThread(parent)
5.{
6. myTimer.start(1);
7. connect(&myTimer, SIGNAL(timeout()), this, SLOT(slotPrint()));
8.}
9.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.}
35.以上代码中,slotPrint()与testFoo()会在两个不同的线程中执行.
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/mmmcu2004/archive/2008/12/07/3466778.aspx
- 理解Qt多线程类
- 理解Qt多线程类
- 理解Qt多线程类
- 理解Qt多线程类
- 理解Qt多线程类
- 理解Qt多线程类
- 理解Qt多线程类(转)
- 深入理解Qt多线程
- 转载Qt多线程的理解
- Qt多线程学习-用例子来理解多线程
- Qt多线程学习-用例子来理解多线程
- Qt多线程学习-用例子来理解多线程(转)
- Qt多线程学习-用例子来理解多线程
- Qt多线程学习-用例子来理解多线程
- Qt多线程学习-用例子来理解多线程
- Qt多线程学习-用例子来理解多线程(转)
- Qt多线程学习-用例子来理解多线程(转)
- Qt多线程学习-用例子来理解多线程
- wininet异步代理的编程
- 禁止eclipse对压缩过的JS提示报错
- poj1201
- UVa 10706 - Number Sequence(POJ 1019)
- 数据库三范式(下)
- 理解Qt多线程类
- MSVC2008 MFC, 无法打开.rc文件, rc:opened in another editor
- C++的继承
- 事件营销让面包圈有关注 但产品好才是真的好
- Windows环境编程 - STARTUPINFO的说明
- typedef函数指针的用法
- VC中CButtonST使用方法
- create procedure example
- hdu 3584 cube #三维树状数组