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多线程以及事件投递的理解的更多相关文章

  1. Qt多线程学习-用例子来理解多线程(转),这个是我看过最好的文章,总结很详细(感觉exec()的作用就是保持线程不退出,这样方便随时处理主线程发来的信号,是一种非常别致的思路)good

    01 class MThread :public QThread 02 { 03 public: 04     MThread(); 05     ~MThread(); 06     virtual ...

  2. Qt多线程学习-用例子来理解多线程

    文章出处:DIY部落(http://www.diybl.com/course/3_program/c/c_js/20090303/157373_3.html) POINT 1:QThread类的实例与 ...

  3. QT虚拟小键盘设计--qt事件循环,事件发送的理解

    有人讲到QT5.7及其以后的版本才自带免费的小键盘插件. QT5.10中关于QKeyEvent类:点击打开链接 QT sendEvent和PostEvent, 点击打开链接 my god,我今天安装了 ...

  4. QT 多线程程序设计【转】

    QT通过三种形式提供了对线程的支持.它们分别是,一.平台无关的线程类,二.线程安全的事件投递,三.跨线程的信号-槽连接.这使得开发轻巧的多线程Qt程序更为容易,并能充分利用多处理器机器的优势.多线程编 ...

  5. Qt多线程编程总结(一)(所有GUI对象都是线程不安全的)

    Qt对线程提供了支持,基本形式有独立于平台的线程类.线程安全方式的事件传递和一个全局Qt库互斥量允许你可以从不同的线程调用Qt方法. 这个文档是提供给那些对多线程编程有丰富的知识和经验的听众的.推荐阅 ...

  6. QT 多线程程序设计(也有不少例子)

    QT通过三种形式提供了对线程的支持.它们分别是,一.平台无关的线程类,二.线程安全的事件投递,三.跨线程的信号-槽连接.这使得开发轻巧的多线程Qt程序更为容易,并能充分利用多处理器机器的优势.多线程编 ...

  7. QT 多线程程序设计 -互斥

    QT通过三种形式提供了对线程的支持.它们分别是,一.平台无关的线程类,二.线程安全的事件投递,三.跨线程的信号-槽连接.这使得开发轻巧的多线程Qt程序更为容易,并能充分利用多处理器机器的优势.多线程编 ...

  8. 【QT】 Qt多线程的“那些事”

    目录 一.前言 二.QThread源码浅析 2.1 QThread类的定义源码 2.2 QThread::start()源码 2.3 QThreadPrivate::start()源码 2.4 QTh ...

  9. 1.QT多线程使用小结

    开头 一个进程可以有一个或更多线程同时运行.线程可以看做是"轻量级进程",进程完全由操作系统管理,线程即可以由操作系统管理,也可以由应用程序管理. Qt 使用QThread来管理线 ...

随机推荐

  1. 20199301《Linux内核原理与分析》第十一周作业

    Linux Capability探索实验 一.实验描述 本实验中,将感受到linux capability功能在访问控制上的优势,掌握使用Capability达到遵守最小权限原则的目的,并分析linu ...

  2. memoryCache 和 diskCache 的相关总结

    一.缓存位置 在浏览器开发者工具的 Network 的 Size 栏会出现的三种情况: from Service Worker from memory cache from disk cache 真正 ...

  3. spark-scala开发的第一个程序WordCount

    package ***** import org.apache.spark.{SparkConf, SparkContext} object WordCount { def main(args: Ar ...

  4. APICloud的tapmode用法

    在开发的过程中,直接给元素绑定事件属性onclick会点击没反应,这时,给标签加上tapmode,就解决了问题,查了一下,原来tapmode具有加速点击事件功能,在触发事件中加入tapmode可以消除 ...

  5. MySQL高级管理

    #mysql数据库密码的修改 一.mysql密码的修改与恢复 1.修改密码 mysqladmin -u root -p123 password 456 数据库内修改 method.first: upd ...

  6. Lightning Web Components 组件样式(四)

    要将样式与组件进行绑定,需要创建一个同名的样式文件,这样样式将会自动应用到组件 在组件中定义的样式的作用域是属于组件的,这样允许组件可以在不同的上下文中可以复用, 可以阻止其他组件的样式的复写 css ...

  7. Nessus简单使用

    1.更新插件 上次搭建完后总觉得不踏实,因为老是提示插件多久没更新了,然后果断花了1.25美刀买了台vps,终于把最新的插件下载下来了,总共190M,需要的QQ私信我.

  8. [C++] 对象指针使用方法

    对象指针:指向类对象的指针 类指针指向类变量(对象)的地址 对象指针定义格式: 类类型 *变量名: 举例: #include <iostream> using namespace std; ...

  9. mysql union all limit的使用

    To apply ORDER BY or LIMIT to an individual SELECT, place the clause inside the parentheses that enc ...

  10. ContextLoadListener & DispatcherServlet 加载顺序以及加载过程

    org.springframework.web.context.ContextLoaderListener 1org.springframework.web.servlet.DispatcherSer ...