QT:moveToThread与信号与槽机制的第五个参数Qt::ConnectionType
来源:互联网 发布:unity3d室内场景建模 编辑:程序博客网 时间:2024/06/05 02:58
原来对QThread的理解,就是重写run(),曾经还一度搞不明白,到底它的槽属于主线程还是子线程。
后来学了MFC,一度觉得MFC的机制比较人性化,起码有工作线程和界面线程的用法,而不像QThread只有run是真正活在子线程里面的。
而直到今天再次研究QThread,发现QThread有很好的功能void QObject::moveToThread(QThread*);
先上代码:
先说毫无疑问的两个功能:一是程序开始,线程启动,而my在线程中,my在线程中打印线程号;二是selfBtn,connect的槽函数完完全全属于主线程的函数,打印主线程线程号。
接下来是三个重点的按钮,三个按钮的连接方式是不一样的。
firstBtn连接的是主线程的槽函数,再在槽函数中执行first(),这样first()是在主线程中调用的,打印出来的是主线程的ID;
secondBtn直接连接myObject中的槽函数,使用的是Qt:DirectConnection直接连接模式,此模式下信号与槽是同步的,信号发出后,直接在信号发送者线程中调用槽函数,由于信号是主线程发出的,因此打印的也是主线程的ID;
thirdBtn也是直接连接myObject中的槽函数,但使用的是QT::QueuedConnection队列连接模式,此模式下信号与槽是异步的,信号发出后,会进入队列中,直到控制权到了接收对象(my)属于的线程(thread)的事件循环时,槽函数才被调用,因此此时打印的是子线程thread的线程ID。
这里重点介绍下connect的第五个参数Qt::ConnectionType。此参数可以有三种选择Qt::AutoConnection、Qt::DirectConnection、Qt::QueuedConnection,分别是自动连接,直接连接和队列连接。正如上面所说,直接连接是同步的,槽函数将和信号同一线程,而队列连接是异步的,槽函数会属于接收对象所属线程。而自动连接是缺省选项,将自动选择直接连接和队列连接之一。而什么时候选择什么连接呢,发送者和接收者处于相同线程,选择直接连接;发送者和接收者处于不同线程,使用队列连接。(看过一篇很有趣的验证文,有兴趣可以参考http://www.cppblog.com/andreitang/archive/2011/08/26/154392.html)
对于上面代码而言QPushButton的三个connect都属于发送者和接收者不在同一个线程,不使用第五个参数的情况下,是默认使用队列连接的,而thread的connect属于发送者和接收者在同一线程,都是thread的线程,默认使用直接连接。
ps:需要注意的是,虽然在connect时,my由主线程生成,还没moveToThread,还在主线程,但在运行时,信号发出的时候,my已经在子线程了,因此自动连接下还是会选择队列连接。自动连接的选择并不是在于对象生成的线程,而是在于对象所处的线程决定的。
好了总结完毕,准备将线程加入到项目中。。。
End
后来学了MFC,一度觉得MFC的机制比较人性化,起码有工作线程和界面线程的用法,而不像QThread只有run是真正活在子线程里面的。
而直到今天再次研究QThread,发现QThread有很好的功能void QObject::moveToThread(QThread*);
先上代码:
widget.h
#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include <QDebug>#include <QThread>class QPushButton;namespace Ui {class Widget;}class myObject : public QObject{ Q_OBJECTpublic: myObject() {} ~myObject() {}public slots: void first() { qDebug()<< QThread::currentThreadId(); } void second() { qDebug()<< QThread::currentThreadId(); } void third() { qDebug()<< QThread::currentThreadId(); }};class Widget : public QWidget{ Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; myObject *my; QPushButton *firstButton,*secondButton,*thirdButton,*selfButton;public slots: void onFirstPushed(); void onSelfPushed();};#endif // WIDGET_H
#include "widget.h"#include "ui_widget.h"#include <QVBoxLayout>#include <QPushButton>Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this); my = new myObject; firstButton = new QPushButton(tr("firstBtn"), 0); connect(firstButton, SIGNAL(clicked()), this, SLOT(onFirstPushed())); secondButton = new QPushButton(tr("secondBtn"), 0); connect(secondButton, SIGNAL(clicked()), my, SLOT(second()), Qt::DirectConnection); thirdButton = new QPushButton(tr("thirdBtn"), 0); connect(thirdButton, SIGNAL(clicked()), my, SLOT(third()), Qt::QueuedConnection); selfButton = new QPushButton(tr("selfBtn"), 0); connect(selfButton, SIGNAL(clicked()), this, SLOT(onSelfPushed())); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(firstButton); layout->addWidget(secondButton); layout->addWidget(thirdButton); layout->addWidget(selfButton); this->setLayout(layout); QThread *thread = new QThread; my->moveToThread(thread); connect(thread, SIGNAL(started()), my, SLOT(first())); thread->start();}Widget::~Widget(){ delete ui;}void Widget::onFirstPushed() { my->first();}void Widget::onSelfPushed() { qDebug() << QThread::currentThreadId();}此代码参考自http://blog.csdn.net/sydnash/article/details/7425947,在度娘找的各种文章中,这篇算是最简洁易懂的,看了这篇再看其它都不成问题了。
先说毫无疑问的两个功能:一是程序开始,线程启动,而my在线程中,my在线程中打印线程号;二是selfBtn,connect的槽函数完完全全属于主线程的函数,打印主线程线程号。
接下来是三个重点的按钮,三个按钮的连接方式是不一样的。
firstBtn连接的是主线程的槽函数,再在槽函数中执行first(),这样first()是在主线程中调用的,打印出来的是主线程的ID;
secondBtn直接连接myObject中的槽函数,使用的是Qt:DirectConnection直接连接模式,此模式下信号与槽是同步的,信号发出后,直接在信号发送者线程中调用槽函数,由于信号是主线程发出的,因此打印的也是主线程的ID;
thirdBtn也是直接连接myObject中的槽函数,但使用的是QT::QueuedConnection队列连接模式,此模式下信号与槽是异步的,信号发出后,会进入队列中,直到控制权到了接收对象(my)属于的线程(thread)的事件循环时,槽函数才被调用,因此此时打印的是子线程thread的线程ID。
这里重点介绍下connect的第五个参数Qt::ConnectionType。此参数可以有三种选择Qt::AutoConnection、Qt::DirectConnection、Qt::QueuedConnection,分别是自动连接,直接连接和队列连接。正如上面所说,直接连接是同步的,槽函数将和信号同一线程,而队列连接是异步的,槽函数会属于接收对象所属线程。而自动连接是缺省选项,将自动选择直接连接和队列连接之一。而什么时候选择什么连接呢,发送者和接收者处于相同线程,选择直接连接;发送者和接收者处于不同线程,使用队列连接。(看过一篇很有趣的验证文,有兴趣可以参考http://www.cppblog.com/andreitang/archive/2011/08/26/154392.html)
对于上面代码而言QPushButton的三个connect都属于发送者和接收者不在同一个线程,不使用第五个参数的情况下,是默认使用队列连接的,而thread的connect属于发送者和接收者在同一线程,都是thread的线程,默认使用直接连接。
ps:需要注意的是,虽然在connect时,my由主线程生成,还没moveToThread,还在主线程,但在运行时,信号发出的时候,my已经在子线程了,因此自动连接下还是会选择队列连接。自动连接的选择并不是在于对象生成的线程,而是在于对象所处的线程决定的。
好了总结完毕,准备将线程加入到项目中。。。
End
0 0
- QT:moveToThread与信号与槽机制的第五个参数Qt::ConnectionType
- qt的Qt::ConnectionType详细以及信号参数传递
- QT的信号与槽机制介绍
- QT的信号与槽机制介绍
- QT的信号与槽机制介绍
- Qt的信号与槽机制介绍
- QT的信号与槽机制介绍
- QT的信号与槽机制介绍
- QT的信号与槽机制介绍
- QT的信号与槽机制介绍
- QT的信号与槽机制介绍
- QT的信号与槽机制介绍
- QT的信号与槽机制
- QT的信号与槽机制介绍
- QT的信号与槽机制介绍
- QT的信号与槽机制介绍
- QT的信号与槽机制介绍
- QT的信号与槽机制介绍
- FPGA笔记 Cyclone IV 供电电源
- 151231_工具遐想
- (搬运)如何正确获得Android内置SD卡跟外置可插拔SD卡
- IE8 未知的运行时错误(ueditor编辑器在ie8、ie7下出现JS错误的解决方法)
- Android开发必备(干货源码放送大)
- QT:moveToThread与信号与槽机制的第五个参数Qt::ConnectionType
- 记录 关于Unicode 转 UTF-8 字符编码
- 【C语言】关于宏定义中#和##符号的使用和宏定义展开问题
- ldap服务器搭建——问题整理
- 撮合系统设计调研(2)
- LINUX-网络-ifconfig
- Android中Canvas绘图详解
- Spring boot将配置属性注入到bean类中
- Android 解决dialog无法弹出输入键盘