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


首先要知道,一个线程在资源分配完之后是以某段代码为起点开始执行的,例如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. Vue-multiselect详解(Vue.js选择框解决方案)

    github地址:https://github.com/shentao/vue-multiselect 官网链接:https://vue-multiselect.js.org/#sub-getting ...

  2. Leetcode初级算法(排序和搜索+数学篇)

    合并两个有序数组 开始的时候将这道题理解错了,发现几个奇怪的测试案例后才明白这道题什么意思.本来的想法就是把nums2全部放到num1里面,然后删除重复元素.排序一下,就有了下面的代码: class ...

  3. avro-maven-plugin

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...

  4. Spring对数据库的操作

    Spring结合Hibernate                   HibernateTemplate http://www.jb51.net/article/41541.htm //////// ...

  5. TCP/IP三次握手与四次挥手的正确姿势

    0.史上最容易理解的:TCP三次握手,四次挥手 https://cloud.tencent.com/developer/news/257281 A 理解TCP/IP三次握手与四次挥手的正确姿势http ...

  6. UVALive - 6442

    题目链接:https://vjudge.net/contest/241341#problem/I 题目大意:输入t,t组样例,输入n,m,有n个圆槽,m个硬币,接下来m行代表每个硬币所在的位子,要求你 ...

  7. ACdream 1236 Burning Bridges 割边 + 去重边

    题目就是求一副图的割边,然后对于那些有重复的边的,不能算做割边. 思路就是每次加入一条边的时候,判断这条边是否存在过,存在过的话,就把那条边设为inf,表示不能作为割边.于是有了这样的代码 #incl ...

  8. Unity Unity脚本类为什么要尽量避免继承MonoBehaviour类?

  9. .net core mvc全局设置跨域访问

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory ...

  10. java关于类的构建

    一开始老是把类的构建和代码的重构搞的混淆,现在理解的可能还好点(至少概念上不会出错了),简单的说类就是一个复杂的变量,这个变量里面含有属性.方法和构造方法,注意方法和构造方法是完全不同的两个概念,而且 ...