Qt多线程学习-用例子来理解多线程

POINT 1:QThread类的实例与普通类的实例没什么不同,只是运行着的run()函数会不同

例1:


class MThread :public QThread
{
public:
            MThread();
           ~MThread();
           void run();
           void foo();
             ...
  
   };


class MDialog :public QDialog
{
       ...
       MThread *mythread;

};

MDialog::MDialog()
 {
       mythread = new MThread;
       ...
}
需要注意的是,在QT中,QThread对象的实例mythread是属于创建它的线程(线程A,即MDialog所在的线程)的,mythread的所 有程序代码与数据都放在与MDialog相同的空间中.这时的mythread,就像任何普通的自己定义的类的实例一样.但是在调用 mythread->start()之后,mythread的run()函数中的代码会在新的线程(线程B)中执行.在run()函数中声明的变 量/实例化的对象,都属于线程B.但是mythread的所有代码,都还在存储在线程A中,只是run()函数的"执行"是在线程B中.

在MDialog中,使用


mythread->foo();
foo()是在线程A中执行的.


在MDialog中使用


connect(this, SIGNAL(sigDialogSignal()), mythread, SLOT(slotThreadSlot()));
当emit sigDialogSignal()时,是会在MDialog所在的线程A中执行的.因为mythread与MDialog同属于一个线程, 这时thread可以看做一个普通类的实例.另外,因为connect函数的连接方式默认是自动连接,而对同属于一个纯种的两个对象,自动连接会使用直接 连接,即slot在发出signal的线程中立即执行.


例2:


#include "mthread.h"

#include <QDebug>

MThread::MThread(QObject *parent) : QThread(parent)
{
       myTimer.start(1);
       connect(&myTimer, SIGNAL(timeout()), this, SLOT(slotPrint()));
}
MThread::~MThread()
{
 

  }

void MThread::run()
{   
  for (int i = 0; i < 100; ++i) {
      for (int j = 0 ; j < 10000; ++j) {
          qDebug()<<"---------"<<i;
      }
   }
   exec();
}


void MThread::slotPrint()
{
    qDebug()<<"==============================";
}
运行后出现:


1....
2....
3.---------9
4.==============================================================
5.---------9
6....
7....
不能误以为:在一个QThread类的派生类中,run()函数中的语句在运行时,可能被本线程定时器超时slot中断. (错误)

事实上,slotPrint()在创建MThread的实例的线程中执行.


POINT 2:线程B中的对象要想接收线程A中的对象发来的signal, 必须进入exec(), 如在exec()前有死循环, 没有进入exec(), 则线程B中的对象不会收到signal.


void MThread::run()
{
   while(1) {
       dosomething(); //此循环永不退出   }
       exec();             //如果此事件循环不能进入,刚此线程不会收到任何signal }
POINT 3:线程A中的指针可指向线程B中创建的对象实例, 这个实例属于线程B. 指针仅仅是一个地址, 而对象实例的变量/代码等都属于线程B.

例1:


class MThread : public QThread
{
      Q_OBJECT
public:
            MThread(QObject *parent = 0);
            ~MThread();
            void run();
            MPrint *mprint;
};
void MThread::run()
{
      mprint = new MPrint;
      exec();
}
//如此声明,mprint所指向的对象属于另一个线程.例2:


class MThread : public QThread
{
   Q_OBJECT
public:
         MThread(QObject *parent = 0);
        ~MThread();
          void run();
         MPrint *mprint;
private:
    QTimer *myTimer;

private slots:
    void slotPrint();   
    void testFoo();
};


void MThread::run()

{

     myTimer = new QTimer;

     mprint = new MPrint;

     myTimer->setInterval(100);

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

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

    exec();

}

以上这样写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. public :
  5.      MThread(QObject *parent = 0);
  6.      ~MThread();
  7.     void run();
  8.      MPrint *mprint;
  9. private :
  10.      QTimer myTimer;


  11. private slots:
  12.     void slotPrint();   
  13.     void testFoo();
  14. };


  15. void MThread::run()
  16. {
  17.      mprint = new MPrint;
  18.      myTimer.setInterval(100);
  19.      connect(&myTimer, SIGNAL(timeout()), this , SLOT(testFoo()));
  20.      QTimer::singleShot(0, &myTimer,SLOT(start()));
  21.     //testFoo();
  22.      exec();
  23. }

以上这样写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. MThread::~MThread()
  10. {

  11. }

  12. void MThread::run()
  13. {
  14.      exec();
  15. }

  16. void MThread::slotPrint()
  17. {
  18.      qDebug()<<"===========================" ;
  19.     for (int i = 0; i < 100; ++i) {
  20.         for (int j = 0 ; j < 10000; ++j) {
  21.              qDebug()<<"---------" <<i;
  22.          }
  23.      }
  24. }

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. MThread::~MThread()
  10. {
  11. }

  12. void MThread::run()
  13. {
  14.      testFoo();
  15.      exec();
  16. }

  17. void MThread::slotPrint()
  18. {
  19.      qDebug()<<"=======================" ;

  20. }

  21. void MThread::testFoo()
  22. {
  23.     for (int i = 0; i < 100; ++i) {
  24.         for (int j = 0 ; j < 10000; ++j) {
  25.              qDebug()<<"---------" <<i;
  26.          }
  27.      }
  28. }
    文章出处:飞诺网(www.firnow.com):http://dev.firnow.com/course/3_program/c/c_js/20090303/157373.html
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值