- 01 class MThread :public QThread
- 02 {
- 03 public:
- 04 MThread();
- 05 ~MThread();
- 06 virtual void run();
- 07 void foo();
- 08 ...
- 09
- 10 };
写在开头的话:本来查看的原文是转载,但是原文给的链接已经失效不知什么情况,自行google标题后在ChinaUnix发现同样的文章没有标注转载字样,不知是否原创,暂时贴ChinaUnix帖子里的链接吧,如有冒犯请原创者联系我,进行修改。
实例代码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多线程学习-用例子来理解多线程
文章出处:DIY部落(http://www.diybl.com/course/3_program/c/c_js/20090303/157373_3.html) POINT 1:QThread类的实例与 ...
- Java多线程学习(一)Java多线程入门
转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79640870 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...
- Android ThreadUtil 线程公共类,判断是否在主线程/ 子线程执行 相关操作
前言:通常,我们写的公共的模块给别人用,但是这个模块又必须在特定的线程中执行. 比如,一个加载网络图片的的方法,需要在子线程中执行. /** * 加载网络图片 */ private void load ...
- Java线程面试题:子线程先运行 2 次,然后主线程运行 4 次,如此反复运行 3 次
package thread; /** * 需求:线程编程:子线程先运行 2 次,然后主线程运行 4 次,如此反复运行 3 次. * @author zhongfg * @date 2015-06-1 ...
- 【转】Delphi多线程学习(9):多线程数据库查询(ADO)
原文:http://www.cnblogs.com/djcsch2001/articles/2382559.html ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用 ...
- Java多线程学习笔记(一)——多线程实现和安全问题
1. 线程.进程.多线程: 进程是正在执行的程序,线程是进程中的代码执行,多线程就是在一个进程中有多个线程同时执行不同的任务,就像QQ,既可以开视频,又可以同时打字聊天. 2.线程的特点: 1.运行任 ...
- (原)Android在子线程用handler发送的消息,主线程是怎么loop到的?
来自知乎:https://www.zhihu.com/question/48130951?sort=created 大家都知道Android的Looper是ThreadLocal方式实现,每个线程 ...
- Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息
之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息,然后在主线程(UI线程)中获取消息并修改UI,那么可以不可以在由主线程发送消息,子线程接收呢?我们按照之前的思路写一下代码: ...
- QT多线程的简单使用,主线程发一份数据,子线程收两份数据
先看效果图,示例发送数据"Hello World" 主线程:0x16f54aeda20,另两个子线程分别是0x4f1baff690.0x4f1baff6a0 因为在子线程中加了20 ...
随机推荐
- google 分屏 横屏模式 按home键界面错乱故障分析(二) 分屏的启动过程
google 进入分屏后在横屏模式按home键界面错乱(二) 你确定你了解分屏的整个流程? imageMogr2/auto-orient/strip%7CimageView2/2/w/1240&quo ...
- inflater-布局转化实现
通俗的说,inflate就相当于将一个xml中定义的布局找出来.因为在一个Activity里如果直接用findViewById()的话,对应的是setConentView()的那个layout里的组件 ...
- Windows/Linux下磁盘使用的图形化工具简介
Windows/Linux下磁盘使用的图形化工具简介 如何以图形界面查看磁盘及分区的大小及剩余容量呢?今天我为大家介绍两款Windows/Linux下磁盘使用的图形化工具分别是Spacesniff ...
- Android ViewPager嵌套ViewPager滑动冲突处理方法
dispatchTouchEvent方法用于事件的分发,Android中所有的事件都必须经过这个方法的分发, 然后决定是自身消费当前事件还是继续往下分发给子控件处理.返回true表示不继续分发,事件没 ...
- javafx image button
public class EffectTest extends Application { public static void main(String[] args) { launch(args); ...
- 银行测试 http://blog.csdn.net/stillming/article/details/42275251
从一家工作了五年的软件公司的测试管理者跳槽到**银行做软件测试,短短两个月,对银行测试有了初步认识,总结和记录下来,加深个人的理解,同时也共享给各位. 银行作为大家的理财顾问,对金钱非常敏感,频繁甚至 ...
- [置顶]
MVC三层架构在各框架中的特征
1.从结构上分析jsp+servlet图解原理: 在基于mvc设计模式下的最原始的jsp+Servlet框架,在某种程度上是不能够达到mvc最直观的体现.当客户端发送请求到服务器时,服务器会将从客户端 ...
- C# Unity依赖注入利用Attribute实现AOP功能
使用场景? 很多时候, 我们定义一个功能, 当我们要对这个功能进行扩展的时候, 按照常规的思路, 我们一般都是利用OOP的思想, 在原有的功能上进行扩展. 那么有没有一种东西, 可以实现当我们需要扩展 ...
- Oracle 12C R2 on Linux 7.X Data Guard 搭建文档
1.查看主机和数据库信息 [oracle@oracle1 ~]$ sqlplus / as sysdba SQL*Plus: Release 12.2.0.1.0 Production on ...
- 深度学习利器: TensorFlow系统架构及高性能程序设计
2015年11月9日谷歌开源了人工智能平台TensorFlow,同时成为2015年最受关注的开源项目之一.经历了从v0.1到v0.12的12个版本迭代后,谷歌于2017年2月15日发布了TensorF ...