文章出处:DIY部落(http://www.diybl.com/course/3_program/c/c_js/20090303/157373_3.html)

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()<<"=============================="; 
}
运行后出现:
 
... 
... 
---------9 
============================================================== 
---------9 
... 
...
不能误以为:在一个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 *myT
文章出处:DIY部落(http://www.diybl.com/course/3_program/c/c_js/20090303/157373.html)
imer; 
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:
 
void MThread::run() 

QTimer myTimer; 
mprint = new MPrint; 
myTimer.setInterval(100); 
connect(&myTimer, SIGNAL(timeout()), this, SLOT(testFoo()), Qt::DirectConnection); 
QTimer::singleShot(0, &myTimer,SLOT(start())); 
//testFoo(); exec(); 
}
以上这样写run(),myTimer在run()中声明,即myTimer属于新的线程,testFoo()也会在新线程中执行.
例4:
 
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() 

mprint = new MPrint; 
myTimer.setInterval(100); 
connect(&myTimer, SIGNAL(timeout()), this, SLOT(testFoo())); 
QTimer::singleShot(0, &myTimer,SLOT(start())); 
//testFoo(); exec(); 
}
以上这样写run(),testFoo()会在创建myTimer的老线程中执行.因为可以看到,mytimer和this(即mythread),都是在同一个线程中,只是在另一个线程中(run()),做了connect操作.
要注意的是,在线程B中启动线程A中的一个定时器,不能使用myTimer.start(),这样启动不了定时器.而应使用signal来触发start()这个slot.
 
POINT 5:slot不会中断同线程中的slot.
例1:
 
#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() 

exec(); 

void MThread::slotPrint() 

qDebug()<<"==========================="; 
for (int i = 0; i < 100; ++i) { 
for (int j = 0 ; j < 10000; ++j) { 
qDebug()<<"---------"<<i; 



slotPrint()函数运行完之后才会退出,说明slot不会中断slot,一个slot在执行完之后才会执行下一个slot.
注意:slotPrint()在创建MThread实例的线程中执行.而不是使用thread->start()创建出的那个线程.
例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() 

testFoo(); 
exec(); 

void MThread::slotPrint() 

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

void MThread::testFoo() 

for (int i = 0; i < 100; ++i) { 
for (int j = 0 ; j < 10000; ++j) { 
qDebug()<<"---------"<<i; 



以上代码中,slotPrint()与testFoo()会在两个不同的线程中执行.

http://blog.csdn.net/liuguangzhou123/article/details/7665198

Qt多线程学习-用例子来理解多线程的更多相关文章

  1. Qt多线程学习-用例子来理解多线程(转),这个是我看过最好的文章,总结很详细(感觉exec()的作用就是保持线程不退出,这样方便随时处理主线程发来的信号,是一种非常别致的思路)good

    01 class MThread :public QThread 02 { 03 public: 04     MThread(); 05     ~MThread(); 06     virtual ...

  2. Java多线程学习(一)Java多线程入门

    转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79640870 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...

  3. Java多线程学习---------超详细总结(java 多线程 同步 数据传递 )

    目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线程状态转换 五线程调度 六常用函数说明 使用方式 为什么 ...

  4. Java多线程学习笔记(一)——多线程实现和安全问题

    1. 线程.进程.多线程: 进程是正在执行的程序,线程是进程中的代码执行,多线程就是在一个进程中有多个线程同时执行不同的任务,就像QQ,既可以开视频,又可以同时打字聊天. 2.线程的特点: 1.运行任 ...

  5. 【转】Delphi多线程学习(9):多线程数据库查询(ADO)

    原文:http://www.cnblogs.com/djcsch2001/articles/2382559.html ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用 ...

  6. Java多线程学习(四)等待/通知(wait/notify)机制

    转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79690279 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...

  7. Java多线程学习(二)synchronized关键字(1)

    转载请备注地址: https://blog.csdn.net/qq_34337272/article/details/79655194 Java多线程学习(二)将分为两篇文章介绍synchronize ...

  8. C#多线程学习之(五)使用定时器进行多线程的自动管理

    本文实例讲述了C#多线程学习之使用定时器进行多线程的自动管理.分享给大家供大家参考.具体分析如下: Timer类:设置一个定时器,定时执行用户指定的函数. 定时器启动后,系统将自动建立一个新的线程,执 ...

  9. Java多线程学习(三)volatile关键字

    转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79680693 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...

随机推荐

  1. Winform 中tabcontrol 美化

    需要对tabcontrol按照美工出的图进行美化 对tabpage页进行标题设置,首先对整个tabcontrol的DrawMode设置为OwnerDrawFixed,由于需要对标题宽度有要求,设置si ...

  2. 在jsp页面里面设置全局引用文件

    head.jsp文件 将项目中所需要用到次数比较多的的插件,库等,同意放在一个jsp文件里面,命名为head.jsp文件,相当于一个全局的 <%@ page language="jav ...

  3. Method and apparatus for encoding data to be self-describing by storing tag records describing said data terminated by a self-referential record

    A computer-implemented method and apparatus in a computer system of processing data generated by a f ...

  4. 十分钟了解 spring cloud

    1 为什么需要服务发现 简单来说,服务化的核心就是将传统的一站式应用根据业务拆分成一个一个的服务,而微服务在这个基础上要更彻底地去耦合(不再共享DB.KV,去掉重量级ESB),并且强调DevOps和快 ...

  5. html head标签的内容跑到body标签中 , 并且body中多了个空格

    今天遇到一个奇怪的问题 , 就是在head标签中写的内容跑到body标签中 , 第一种也是经常遇到的情况就是编码 UTF-8 格式带BOM的 , 这种情况是会多一个空格 , 这个基本都知道 , 按ut ...

  6. Linux开关命令(shutdown,reboot,halt,init)

    命令简短 shutdown,poweroff,reboot,halt,init都能够进行关机,大致使用方法. /sbin/halt     [-n] [-w] [-d] [-f] [-i] [-p] ...

  7. Linux(CentOS 7)+ Nginx(1.10.2)+ Mysql(5.7.16)+ PHP(7.0.12)完整环境搭建

    首先安装Linux系统,我以虚拟机安装来做示例,先去下载 VitualBox,这是一款开源的虚拟机软件,https://www.virtualbox.org 官网地址.或者是VMware,www.vm ...

  8. uva 11346 - Probability(可能性)

    题目链接:uva 11346 - Probability 题目大意:给定x,y的范围.以及s,问说在该范围内选取一点,和x,y轴形成图形的面积大于s的概率. 解题思路:首先达到方程xy ≥ s.即y ...

  9. QT下的几种透明效果(QPalette背景白色,窗口设置setWindowOpacity,QPainter使用Clear模式绘图)

    1.窗口整体透明,但是窗体上的控件不透明.    通过设置窗体的背景色来实现,将背景色设置为全透. QPalette pal = palette(); pal.setColor(QPalette::B ...

  10. Nginx支持LInux的软链接或硬链接

    在我们配置nginx的时候,有些时候,大部分都是讲root指向真实的目录.但是有些时候,我们需要指向一个软链接.但是配置的时候,发现会有问题. 我们可以通过以下的方法,来解决,让nginx支持软链接/ ...