Qt——QThread

事件驱动与事件循环

1、QT是事件驱动。在建立工程时,main.cpp如下部分代码,QAplication::exec()即启动了事件循环,每一个信号被当做事件来排队处理。

	QApplication a(argc, argv);
	/*...*/
    return a.exec();

2、模态对话框和事件循环参考这里
1)QWidget有非模态和模态两种展示方式
即QWidget::show() & QWidget::exec()。
2)实际上,QWidget::exec() 就是 setAttribute+show()+eventloop
3)QDialog继承自QWidget,对于模态对话框,会启用自己的事件循环。此时,主线程的事件循环阻塞,等待模态对话框的事件循环结束后,解除阻塞。
4)模态对话框的事件循环不会在单独的子线程执行,因此,事件循环跟线程没有必然联系。

QThread

1、QThread子类成员函数的运行线程
继承自QThread的类,在使用过程中,对于不在run()函数内执行的成员函数,比如一些槽函数,一般是在主线程运行(因为QThread子类本身一般是在主线程)。如何使其在次线程执行?
首先,明白一下几点
1)QThread负责管理线程,管理的线程(子线程)和依附的线程不同。
2)QThread::run()如同main(),运行run则开启线程、结束run则结束线程。
3)对于信号与槽,connect函数强调发送信号的线程和接受者依附的线程。
connect函数的最后一个参数:队列连接(槽函数在接受者依附的线程执行)、直接连接(槽函数在信号发射的线程执行)…

然后,想要成员函数在次线程运行
1)正常创建QThread对象。
2)把需要的槽或者函数写成一个类(就叫Class吧),继承自QObject。
3)把这个Class类的实例化对象转移到次线程。

class Class: public QObject

QThread t
Class c
c.moveToThread(&t)

2、跨线程指针的new和delete
对于上述实例化的对象(上述的c)中,如果需要给指针new一个空间,不能在构造函数中new,同样也不能在析构函数中delete。
因为指针的使用是在次线程,而构造和析构是在主线程完成,当关闭程序时,会报错(Cannot send events to objects owned by a different thread)。
解决方法是将指针的new和delete放到类(上述的Class)的槽函数中,通过主线程发送信号实现构造和释放。看这里。
要注意的是要确保delete在线程quit之前,如果这两个动作一前一后执行,比如下面这样,建议connect方式用Qt::BlockingQueuedConnection

	emit toDelete();
    t.quit();

3、跨线程信号与槽问题1——次线程的槽不执行
上面的解决方法会涉及到跨线程的信号和槽,一般我们在connect时可以通过Qt::AutoConnection或者Qt::QueuedConnection的方式实现跨线程的连接。
理论上,这就足够了,但实际上,尽管使用Qt::QueuedConnection,仍可能出现主程序的信号无法触发从线程中QObject子类对象的槽。
原因参考这里。
1)只有当从线程的消息循环正在运行的时候,才能正常接收信号或者说事件。
2)QThread的exec会开消息循环,调用start接口默认会执行exec,因此也会开消息循环。
3)start启线程后是否执行exec取决于run接口的实现,默认是调exec;如果重写了run接口,修改了默认行为,不再执行exec,也就不会运行消息循环。

4、跨线程信号与槽问题2——如何在次线程connect
把主线程的对象的指针通过信号发送到次线程。

注意!!!次线程内部的信号槽的连接建议用Qt::DirectConnection。

参考

1、https://blog.csdn.net/lynfam/article/details/7081757
2、https://blog.csdn.net/dbzhang800/article/details/6300416
3、https://www.cnblogs.com/judes/p/12943716.html
4、https://blog.csdn.net/u011388696/article/details/107854759

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值