这是一篇随记,排版什么的就没有那么好了:)


首先要知道,一个线程在资源分配完之后是以某段代码为起点开始执行的,例如STL内的std::thread,POSIX下的pthread等,都是以函数加其参数之后在新线程内调用运行的,但是,Qt的却进行了一个封装,要使用Qt的QThread,核心思想就是将对象在线程内创建或移入线程中,之后通过那些在线程内的对象的信号和槽方式与其他线程进行交互,这里就衍生出来了两种写法(虽然核心思想都是一样的):

  • 第一种:
...
class myThread:
public QThread{
private:
myObj1 obj1; //注意,这两个对象都要继承自QObject,
myObj2 obj2; //否则不能使用信号和槽,而且没有moveToThread这个方法
public:
myThread(){
obj1.moveToThread(this);
obj2.moveToThread(this);
}
void run() override{
myObject3 obj3; //此时该对象本省就是线程内的对象了,不需要继承自QObject
//但是缺点在于,要以多线程的方式
//即在当前线程内使用该对象的方法,只能在当前函数内调用
//这实际上是与Qt的开发思想是相悖的,Qt的多线程开发思想就是
//借助信号和槽的机制,以当前线程的槽队列来进行线程内的对象
//与其他线程内交互
...
...
exec(); //进入事件循环等待信号的发出
}
public slots:
void slot1(){
...
}
};
...

其实不难想,QThread的线程入口就是他的run函数,置于其他的,遵从一个原则:


所有的资源(包括信号和槽函数),都是属于创建该对象的那个线程的,所以不难想到在当前myThread中的任何一个信号和槽都将会在默认情况下在创建这个对象的那个线程内执行,比如:

int main(int a,char **b){
QtCoreApplication a(a,b);
QTimer tmer;
myThread mTh;
QObject::connect(&tmer,"timeout()",&mTh,"slot1()");
tmer.start(1s);
return a.exec()
}

很明显,在QTimer触发timeout()信号的时候,槽slot1始终在当前线程(主程)内调用


接下来就要隆重介绍两种主要的信号,槽的连接方式了:


Qt::QueueConnection和Qt::DirectConnection


第一种就是将当前的信号放入槽所属的对象的事件循环队列内


第二种是直接在当前线程内调用槽函数,直接调用自然可以知道,执行槽函数的线程就是当前的信号所属的线程


通常默认情况下,连接方式是Qt:AutoConnection,该方式判断,如果信号和槽所属的是一个线程,那么此时使用Qt::DirectConnection,否则使用Qt::QueueConnection


但是注意:


在上面那个例子中,connect不论以何种方式进行信号槽的调用,都将是在主线程内调用的,援引在之前已经说到了,myThread对象的创建线程就是主线程,所以信号和槽均属于主线程,不存在跨线程的情况

  • 第二种:
...
int main(int a,char **b){
QtCoreApplication a(a,b);
QThread sgThread;
myObj1 obj1;
obj1.moveToThread(&sgThread);
QTimer tmer;
QObject::connect(&tmer,"timeout()",&obj1,...,Qt::DirectConnection);
//此时obj1的槽会被主线程调用
QObject::connect(&tmer,"timeout()",&obj1,...);
//此时默认Queue,所以会在sgThread所创建的那个中调用
tmer.start(1s);
return a.exec();
}
...

实际上,第一种和第二种是一模一样的思路和方法,只是moveToThread的位置不同,但是要注意:moveToThread不是线程安全的,换句话说,moveToThread只能是在当前线程和参数所指线程对象不同的情况下才能正确调用,因此第一种方式和第二种方式是一致的.

Qt之QThread随记的更多相关文章

  1. Qt之QThread(深入理解)

    简述 为了让程序尽快响应用户操作,在开发应用程序时经常会使用到线程.对于耗时操作如果不使用线程,UI界面将会长时间处于停滞状态,这种情况是用户非常不愿意看到的,我们可以用线程来解决这个问题. 前面,已 ...

  2. 解析Qt中QThread使用方法

    本文讲述的是在Qt中QThread使用方法,QThread似乎是很难的一个东西,特别是信号和槽,有非常多的人(尽管使用者本人往往不知道)在用不恰当(甚至错误)的方式在使用QThread,随便用goog ...

  3. Qt线程QThread简析(8个线程等级,在UI线程里可调用thread->wait()等待线程结束,exit()可直接退出线程,setStackSize设置线程堆栈,首次见到Qt::HANDLE,QThreadData和QThreadPrivate)

    QThread实例代表一个线程,我们可以重新实现QThread::run(),要新建一个线程,我们应该先继承QThread并重新实现run()函数. 需要注意的是: 1.必须在创建QThread对象之 ...

  4. Qt多线程-QThread

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt多线程-QThread     本文地址:http://techieliang.com/2 ...

  5. Qt之QThread

    简述 QThread类提供了与系统无关的线程. QThread代表在程序中一个单独的线程控制.线程在run()中开始执行,默认情况下,run()通过调用exec()启动事件循环并在线程里运行一个Qt的 ...

  6. Qt线程—QThread的使用--run和movetoThread的用法

    Qt使用线程主要有两种方法: 方法一:继承QThread,重写run()的方法 QThread是一个非常便利的跨平台的对平台原生线程的抽象.启动一个线程是很简单的.让我们看一个简短的代码:生成一个在线 ...

  7. QT下QThread学习(二)

    学习QThread主要是为了仿照VC下的FTP服务器写个QT版本.不多说,上图. FTP服务器的软件结构在上面的分析中就已经解释了,今天要解决的就是让每一个客户端的处理过程都可以按一个线程来单独跑.先 ...

  8. 【QT】 QThread部分源码浅析

    本文章挑出QThread源码中部分重点代码来说明QThread启动到结束的过程是怎么调度的.其次因为到了Qt4.4版本,Qt的多线程就有所变化,所以本章会以Qt4.0.1和Qt5.6.2版本的源码来进 ...

  9. 【QT】QThread源码浅析

    本章会挑出QThread源码中部分重点代码来说明QThread启动到结束的过程是怎么调度的.其次因为到了Qt4.4版本,Qt的多线程就有所变化,所以本章会以Qt4.0.1和Qt5.6.2版本的源码来进 ...

随机推荐

  1. CCF201612-1 中间数(二分思想)

    问题链接:CCF201612试题. .对n个数进行排序,找出中间那个数,然后将中间那个数的左右与其相等的数去掉,看左右剩下的数个数是否相等,如果相等则中间那个数就是答案,否在输出-1. 问题描述 问题 ...

  2. 未找到与约束 Micorosoft.CodeAnalysis.Editor.TypeScript.ToolsOptions.IUserSettingsProvider

    问题: 未找到与约束  ContractName Micorosoft.CodeAnalysis.Editor.TypeScript.ToolsOptions.IUserSettingsProvide ...

  3. django 请求生命周期

    详细例子:

  4. spring boot中ConditionalOnClass为什么没有classNotFound类加载异常

    查看原码时有很多飘红的地方, 这些import都失败的地方, 为什么在运行时没有报错? 首先这些@Configuration类没有被程序中的类引用到 其次即使引用到这个类,不一定引用到类中的具体某个方 ...

  5. 023 Merge k Sorted Lists 合并K个有序链表

    合并K个有序链表,并且作为一个有序链表的形式返回.分析并描述它的复杂度. 详见:https://leetcode.com/problems/merge-k-sorted-lists/descripti ...

  6. Python3基础(4)匿名函数、装饰器、生成器、迭代器、内置函数、json&pickle序列化、软件目录开发规范、不同目录间模块调用

    ---------------个人学习笔记--------------- ----------------本文作者吴疆-------------- ------点击此处链接至博客园原文------ 1 ...

  7. 解决gradle下载慢的问题

    解决方法要做两部 一 打开用户主目录 linux平台/home/用户名/.gradle windows平台c:\Users\用户名\.gradle macos平台/Users/用户名/.gradle ...

  8. spring boot注入error,Consider defining a bean of type 'xxx' in your configuration问题解决方案

    经常出现这问题一定是非spring生态圈的@标签 没被spring引入,如mybatis等 因为在默认情况下只能扫描与控制器在同一个包下以及其子包下的@Component注解,以及能将指定注解的类自动 ...

  9. window.open 打开Excel或者Word 无权限问题

    场景:后端C# ashx 前端:js js在对ashx返回结果进行window.open(url)  url为后端保存excel的一个地址 提示:无操作权限 url:为后端处理后,服务器上一个完整的路 ...

  10. C 碎片七 指针

    一.地址和指针 程序在编译过程中,系统会根据变量类型分配一定长度的内存单元.内存区中的每个字节都有一个编号,该内存单元的初始编号就是变量的"地址/指针",该内存单元的长度就是变量的 ...