对QT多线程以及事件投递的理解
1、使用QObject子类的movetothread方法 代替 QThread子类的run 实现多线程。
使用原始QThread对象的start方法启动线程==>连接原始QThread对象的started信号到QObject子类的槽(线程部分)。
2、有parent的object是不能moveToThread被移动到其他线程中的,所以还需要把子类对象给setParent(NULL)一下再moveToThread。
3、QObject子类对象在movetothread后,不要在线程中进行delete,因为QObject子类对象的内存管理还属于主线程。
4、QCoreApplication::exec()开启了主线程的事件循环。子线程也是一样,需要通过调用exec开启事件循环,否则事件不会分发给对对象。
QThread线程并不存在exec()函数。原因是exec()函数在QThread的run()中已经调用了。
5、postEvent: 可以给别的线程发送事件。事件会在目的对象所属的线程中运行。异步接口。
sendEvent: 仅用于同一个线程之间发送事件。目的对象必须与当前线程一样。同步接口
6、跨线程的事件传递可以通过 QCoreApplication::postEvent 和 重载QObject类的customEvent的方法 实现。
--------------------------------------------------------------------------------------------------------------------
1) 用原始的QThread的started信号触发自定义的slot启动线程(需要connect这个QThread对象的started信号),
而不是派生QThread的类重载run函数启动线程。
将一个类派生自QObject,然后实现所有的signal/slot,然后通过调用movetothread函数来使他们执行在新的线程里面,
而不是每次都要重新派生QThread,并且派生QThread的另外一个不好的地方是只有run函数内部的代码才会执行在新线程里面,
相比起来,派生QObject并使用movetothread函数更具有灵活性。
2) 自定义对象(QObject子类)moveToThread进线程后,事件循环可以完全在此线程中运行。而它的内存管理应该还属于主线程。
有parent的object是不能moveToThread被移动到其他线程中的,所以还需要把子类对象给setParent(NULL)一下再moveToThread.
如下例子中(MyObject* myObj)被moveToThread进线程(QThread *thread),假如对象(MyObject* myObj)有父亲,它不能移动这种关系。
在另一个线程(而不是创建它的那个线程)中delete QObject对象是不安全的。除非你可以保证在同一时刻对象不在处理事件。
可以用QObject::deleteLater(),它会投递一个DeferredDelete事件,这会被对象线程的事件循环最终选取到。
3)exec的重要性。
主线程开始它的事件循环需要调用QCoreApplication::exec(), 子线程需要用QThread::exec(),功能基本是一样的,当然qt内部肯定是不同的实现。
假如没有事件循环运行,事件不会分发给对象。
举例来说,假如你在一个线程中创建了一个QTimer对象,但从没有调用过exec(),那么QTimer就不会发射它的timeout()信号.
对deleteLater()也不会工作。(这同样适用于主线程)。
4) 子线程接收事件
a) 如下例子中,子线程并不存在exec()函数。原因是exec()函数在QThread的run()中调用了。
我们这里并没有做一个QThread派生类,在run中调用exec()。因为我不推荐怎么干。原因很简单,并不需要这么干。
进一步说明是:qt提供的QThread已经完全满足线程创建的需要。为什么还要自己再画蛇添足呢。
b)本例子真正使用的是QCoreApplication::postEvent,和重载QObject类的customEvent的方法。消息一样会在(MyObject* myObj)所在的线程处理。
5) 关于QCoreApplication::postEvent和QCoreApplication::sendEvent
postEvent: 可以给别的线程发送事件。事件会在目的对象所属的线程中运行。这是一个异步接口。
sendEvent: 仅用于同一个线程之间发送事件。目的对象必须与当前线程一样。这是一个同步接口。假如发送给属于另一个线程的对象,会报错:ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread a51f48. Receiver '' (of type
'MyObject') was created in thread a3bf18", file kernel\qcoreapplication.cpp, line 539
代码片段如下:(完整例子请到转载地址查看)
const QEvent::Type CustomEvent_Login = ( QEvent::Type )5001; //! 建议用5000以上唯一的标识
void MyObject::customEvent( QEvent *e )
{
if ( e->type() == CustomEvent_Login ) //捕获消息
{
qDebug() << QString( "[%1]catch the event: %2!" )
.arg( ( qlonglong )QThread::currentThreadId() )
.arg( e->type() );
}
}
int main( int argc, char *argv[] )
{
QCoreApplication a( argc, argv );
qDebug() << "main:" << ( qlonglong )QThread::currentThreadId();
//把业务逻辑对象设置进线程,不要把Qthread放进自己线程,这样的写法不建议。
//绑定的时候最好设置QueuedConnection。这样就允许在myObj线程执行,否则可能会在主线程执行。
//如果希望不要再子线程执行,用DirectConnection。
MyObject *myObj = new MyObject;
QThread *thread = new QThread();
myObj->moveToThread( thread );
thread->start();
QObject::connect( thread, SIGNAL( started() ), myObj, SLOT( OnStartedSlot() ), Qt::QueuedConnection );
//定时器
//MyObject::Started/MyObject::Timeout/都会在同一个子线程调用。
QTimer *timer = new QTimer();
QObject::connect( timer, SIGNAL( timeout() ), myObj, SLOT( OnTimeoutSlot() ), Qt::QueuedConnection );
timer->start( 1000 );
//发送事件
QCoreApplication::postEvent( myObj, new QEvent( CustomEvent_Login ) );
qDebug() << QString( "[%1]send the event: %2!" )
.arg( ( qlonglong )QThread::currentThreadId() )
.arg( CustomEvent_Login );
return a.exec();
}
转载地址:http://blog.csdn.net/shaochat/article/details/41956707?utm_source=tuicool
http://blog.csdn.net/sonydvd123/article/details/8660624
对QT多线程以及事件投递的理解的更多相关文章
- Qt多线程学习-用例子来理解多线程(转),这个是我看过最好的文章,总结很详细(感觉exec()的作用就是保持线程不退出,这样方便随时处理主线程发来的信号,是一种非常别致的思路)good
01 class MThread :public QThread 02 { 03 public: 04 MThread(); 05 ~MThread(); 06 virtual ...
- Qt多线程学习-用例子来理解多线程
文章出处:DIY部落(http://www.diybl.com/course/3_program/c/c_js/20090303/157373_3.html) POINT 1:QThread类的实例与 ...
- QT虚拟小键盘设计--qt事件循环,事件发送的理解
有人讲到QT5.7及其以后的版本才自带免费的小键盘插件. QT5.10中关于QKeyEvent类:点击打开链接 QT sendEvent和PostEvent, 点击打开链接 my god,我今天安装了 ...
- QT 多线程程序设计【转】
QT通过三种形式提供了对线程的支持.它们分别是,一.平台无关的线程类,二.线程安全的事件投递,三.跨线程的信号-槽连接.这使得开发轻巧的多线程Qt程序更为容易,并能充分利用多处理器机器的优势.多线程编 ...
- Qt多线程编程总结(一)(所有GUI对象都是线程不安全的)
Qt对线程提供了支持,基本形式有独立于平台的线程类.线程安全方式的事件传递和一个全局Qt库互斥量允许你可以从不同的线程调用Qt方法. 这个文档是提供给那些对多线程编程有丰富的知识和经验的听众的.推荐阅 ...
- QT 多线程程序设计(也有不少例子)
QT通过三种形式提供了对线程的支持.它们分别是,一.平台无关的线程类,二.线程安全的事件投递,三.跨线程的信号-槽连接.这使得开发轻巧的多线程Qt程序更为容易,并能充分利用多处理器机器的优势.多线程编 ...
- QT 多线程程序设计 -互斥
QT通过三种形式提供了对线程的支持.它们分别是,一.平台无关的线程类,二.线程安全的事件投递,三.跨线程的信号-槽连接.这使得开发轻巧的多线程Qt程序更为容易,并能充分利用多处理器机器的优势.多线程编 ...
- 【QT】 Qt多线程的“那些事”
目录 一.前言 二.QThread源码浅析 2.1 QThread类的定义源码 2.2 QThread::start()源码 2.3 QThreadPrivate::start()源码 2.4 QTh ...
- 1.QT多线程使用小结
开头 一个进程可以有一个或更多线程同时运行.线程可以看做是"轻量级进程",进程完全由操作系统管理,线程即可以由操作系统管理,也可以由应用程序管理. Qt 使用QThread来管理线 ...
随机推荐
- centos7安装yum安装pip
pip是python中的一个包管理工具,可以对Python包的查找.下载.安装.卸载的作用. yum -y install epel-release yum -y install python-pip ...
- 一行代码搞定WordPress面包屑导航breadcrumb
有好几位网友在问WordPress面包屑导航breadcrumb怎么操作,网上有些教程是去function文件中定义,其实不用那么复杂,很简单一行代码就能搞定.下面随ytkah一起来看看.如果是单页, ...
- 【AirTest自学】AirTest工具介绍和入门学习(一)
==================================================================================================== ...
- 安装cuda及之后更新环境变量的方法
安装参考:https://www.cnblogs.com/fanfzj/p/8521728.html 更新环境变量: 将 CUDA.CUPTI 和 cuDNN 安装目录添加到 %PATH% 环境变量中 ...
- Logistic Regression Algorithm
逻辑回归算法LR. 简介 逻辑回归是机器学习从统计学领域借鉴的另一种技术.它是二进制分类问题的首选方法(有两个类值的问题). Logistic回归就像线性回归,目标是找到权重每个输入变量的系数值. ...
- 解决configure: WARNING: You will need re2c 0.13.4 or later
我在安装rabbitmq php扩展的时候发现 configure: WARNING: You will need re2c 0.13.4 or later if you want to regene ...
- 洛谷P4380 [USACO18OPEN]Multiplayer Moo
题目 第一问: 用广搜类似用\(floodfill\)的方法. 第二问: 暴力枚举加剪枝,对于每个连通块,枚举跟这个连通块相连的其他与他颜色不同的连通块,然后向外扩展合并颜色与他们俩相同的连通块.扩展 ...
- react用脚手架创建一个react单页面项目,react起手式
官网地址:https://react.docschina.org/ 确保本地安装了Node.js node的版本大于8.10 npm的版本大于5.6 1.在本地的某个位置创建一个文件夹,执行以下 ...
- URL的作用是什么?它由几部分组成?
URL是统一资源定位符,对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址.互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它 ...
- mysql 根据发音查找内容
当前表 mysql> select * from table1; +----------+------------+-----+ | name_new | transactor | pid | ...