1. 01 class MThread :public QThread
  2. 02 {
  3. 03 public:
  4. 04     MThread();
  5. 05     ~MThread();
  6. 06     virtual void run();
  7. 07     void foo();
  8. 08     ...
  9. 09
  10. 10 };

写在开头的话:本来查看的原文是转载,但是原文给的链接已经失效不知什么情况,自行google标题后在ChinaUnix发现同样的文章没有标注转载字样,不知是否原创,暂时贴ChinaUnix帖子里的链接吧,如有冒犯请原创者联系我,进行修改。

(不确定是否为原文链接):http://bbs.chinaunix.net/thread-3642263-1-1.html
实例代码1:
 
POINT 1:QThread类的实例与普通类的实例没什么不同,只是运行着的run()函数会不同(自己注:run中的内容会在另外的线程中运行)
 
实例代码2:
 
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中,使用
 
mythread->foo();
foo()是在线程A中执行的.
 
在MDialog中使用
 
connect(this, SIGNAL(sigDialogSignal()), mythread, SLOT(slotThreadSlot()));
当emit sigDialogSignal()时,是会在MDialog所在的线程A中执行的.因为mythread与MDialog同属于一个线程, 这时thread可以看做一个普通类的实例.另外,因为connect函数的连接方式默认是自动连接,而对同属于一个纯种的两个对象,自动连接会使用直接连接,即slot在发出signal的线程中立即执行.
 
实例代码3:
 
 
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 }
 
 
 
运行后出现:
 
... 
... 
---------9 
============================================================== 
---------9 
... 
...
不能误以为:在一个QThread类的派生类中,run()函数中的语句在运行时,可能被本线程定时器超时slot中断. (错误)
事实上,slotPrint()在创建MThread的实例的线程中执行,而run()函数在新的线程中运行。
 
POINT 2:线程B中的对象要想接收线程A中的对象发来的signal, 必须进入exec(), 如在exec()前有死循环, 没有进入exec(), 则线程B中的对象不会收到signal.
 
实例代码4:
1 void MThread::run()  
2 {  
3     while(1) {  
4         dosomething();  //此循环永不退出  
5     }  
6     exec();             //如果此事件循环不能进入,则此线程不会收到任何signal  
7 }
 
 
POINT 3:线程A中的指针可指向线程B中创建的对象实例,  这个实例属于线程B. 指针仅仅是一个地址(自己补充:存放地址的变量,而不是地址), 而对象实例的变量/代码等都属于线程B.
实例代码5:
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所指向的对象属于另一个线程,即原始线程.
 
 
实例代码6:
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()会在新线程中执行.
 
 
实例代码7:
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()也会在新线程中执行.
 
实例代码8:
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.
实例代码8:
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()创建出的那个线程.
实例代码8:
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()会在两个不同的线程中执行.(自己注:slotPrint和MThread同一个线程中运行,而testFoo会在run()新生成的线程中运行)

https://blog.csdn.net/msccreater/article/details/8821062

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

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

    文章出处:DIY部落(http://www.diybl.com/course/3_program/c/c_js/20090303/157373_3.html) POINT 1:QThread类的实例与 ...

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

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

  3. Android ThreadUtil 线程公共类,判断是否在主线程/ 子线程执行 相关操作

    前言:通常,我们写的公共的模块给别人用,但是这个模块又必须在特定的线程中执行. 比如,一个加载网络图片的的方法,需要在子线程中执行. /** * 加载网络图片 */ private void load ...

  4. Java线程面试题:子线程先运行 2 次,然后主线程运行 4 次,如此反复运行 3 次

    package thread; /** * 需求:线程编程:子线程先运行 2 次,然后主线程运行 4 次,如此反复运行 3 次. * @author zhongfg * @date 2015-06-1 ...

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

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

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

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

  7. (原)Android在子线程用handler发送的消息,主线程是怎么loop到的?

    来自知乎:https://www.zhihu.com/question/48130951?sort=created   大家都知道Android的Looper是ThreadLocal方式实现,每个线程 ...

  8. Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息

    之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息,然后在主线程(UI线程)中获取消息并修改UI,那么可以不可以在由主线程发送消息,子线程接收呢?我们按照之前的思路写一下代码: ...

  9. QT多线程的简单使用,主线程发一份数据,子线程收两份数据

    先看效果图,示例发送数据"Hello World" 主线程:0x16f54aeda20,另两个子线程分别是0x4f1baff690.0x4f1baff6a0 因为在子线程中加了20 ...

随机推荐

  1. VPS搭建与IPv6使用教程

    VPS搭建与IPv6使用教程 SoftEther命令: yum -y install gcc zlib-devel openssl-devel readline-devel ncurses-devel ...

  2. C# 向DataTable中插入数据或伪造DataTable

    方法一: DataTable  tblDatas = new DataTable("Datas"); DataColumn dc = null; dc = tblDatas.Col ...

  3. ByteUtils

    package sort.bing.com; import java.io.ByteArrayOutputStream;import java.io.DataOutputStream;import j ...

  4. 配置mysql的ODBC数据源

    如果你已经安装好了mysql和mysql连接驱动,则可以向下进行了 打开控制面板,以小图标的形式查看,找到管理工具 打开管理工具,找到数据源(odbc),打开 在图片中所圈出的三个标签中随便选一个,点 ...

  5. MySQL 使用mysqld_multi部署单机多实例详细过程

    ,如何使用多实例 由于多实例中,各个实例的资源都是不share的,所以要合理分配好各个实例的内存.磁盘等资源,避免out of memery或则 full disk的情况出现.

  6. 洛谷 P2562 [AHOI2002]Kitty猫基因编码

    P2562 [AHOI2002]Kitty猫基因编码 题目描述 小可可选修了基础生物基因学.教授告诉大家 Super Samuel 星球上 Kitty猫的基因的长度都是 2 的正整数次幂 ), 全是由 ...

  7. 【SSH学习笔记】—从配置Struts1环境到简单实例

    以下我将从一个简单点的计算器实例,介绍struts1的环境配置,以及其重要的两个核心类:ActionForm和Action  简单计算器实现思路: 1.提供一个输入界面,输入两个数字和运算符(+.-. ...

  8. 鸟哥的Linux私房菜-----16、程序与资源管理

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...

  9. vue权限控制菜单显示的简单实现

    为了对于不同角色显示不同的菜单 思路1: 本地放一份完整的菜单数据,通过后台返回角色的菜单列表.两者对比,筛选需要显示的菜单数据绑定, 这里有个问题就是路由vue实例初始化就生成了,加载的全部,人为输 ...

  10. [selenium]选取下拉框内容的方法

    说明:本文章主要是对select元素操作的讲解,非select元素的下拉框需要另外分析 1.select元素示例: 2.select下拉框选取的3种方法 WebElement selector = d ...