zoukankan      html  css  js  c++  java
  • Qt 跨UI线程的数据交换和信号-槽调用实现方案汇总

    一、目录

     转载1: http://my.oschina.NET/fanhuazi/blog/737224?ref=myread 点击打开链接

     转载2: http://www.qtcn.org/bbs/read-htm-tid-60505-ds-1-page-1.html#172183 点击打开链接

    二、内容

    由于以下两篇转载文章都使用了C++11 新特性“lamda表达式”,为了方便同仁阅读以下内容,在此引用一片文章对“C++11 lamda表达式”做一个简要介绍:

    “C++11 lamda表达式”  ,点击此链接先了解C++11新增语法,对后面内容的阅读会有帮助。

    转载1: http://my.oschina.Net/fanhuazi/blog/737224?ref=myread 点击打开链接

    在Qt中将函数发送到主线程执行

    ……(省略部分内容,完成内容请参看上面的原文链接)数据共享的问题,试想“后台线程(非UI线程)中的数据如何能够被前台(UI线程)所使用,而且前台后台不一定在一个类里面?把数据打包通过信号传给前台?”想想就是很麻烦的事情,难道每个这样的需求场合都要做一遍这样的事情吗?感谢时间,因为时间穿过2011年,C++的新标准已经完美的解决了这个问题,那就是函数对象。
    Qt的4.8.6版本所使用的mingw4.9.2版本是支持C++11的,如果你用的是老掉牙的rhel5系统,则需要升级编译器了,因为C++11要在GCC 4.5以上的版本中才会支持。
    首先我们定义一个类:FunctionTransfer(函数大挪移),这个类继承自QObject,并使用Q_OBJECT标签来使用信号槽机制。代码中的“std::tr1::function<void()>”就是C++标准库中大名鼎鼎的函数对象。

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. class FunctionTransfer : public QObject  
    2.   
    3. {  
    4.     Q_OBJECT  
    5.   
    6. public:  
    7.   
    8.     ///@brief 构造函数  
    9.   
    10.     explicit FunctionTransfer(QObject *parent = 0);  
    11.   
    12. public:  
    13.   
    14.     ///@brief 制定函数f在main中执行  
    15.   
    16. static void execinmain(std::tr1::function<void()> f);  
    17.   
    18. signals:  
    19.   
    20.     ///@brief 在别的线程有函数对象传来  
    21.   
    22.     void comming(std::tr1::function<void()> f);  
    23.   
    24. public slots:  
    25.   
    26.     ///@brief 执行函数对象  
    27.   
    28.     void exec(std::tr1::function<void()> f);  
    29. };  

    然后是源文件:

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //在全局数据区实例化一个FunctionTransfer的实例,该实例所在的县城就是主线程。  
    2.   
    3. FunctionTransfer main_thread_forward;  
    4. void FunctionTransfer::execinmain(std::tr1::function<void()> f)  
    5. {  
    6.     main_thread_forward.exec(f);  
    7. }  
    8.    
    9. FunctionTransfer::FunctionTransfer(QObject *parent) :  
    10.     QObject(parent)  
    11. {  
    12.     connect(this,SIGNAL(comming(std::tr1::function<void()>)),this,SLOT(exec(std::tr1::function<void()>)),Qt::BlockingQueuedConnection);  
    13. }  
    14.    
    15.    
    16. void FunctionTransfer::exec(std::tr1::function<void()> f)  
    17. {  
    18.     if(Gt::isMainThread())  
    19.     {  
    20.         f();  
    21.     }  
    22.     else  
    23.     {  
    24.         emit this->comming(f);  
    25.     }  
    26. }  


    非常简单的逻辑,如果在主线程就执行,如果不是在主线程就发给主线程,主线程接到之后就执行。
    类有了,接下来考虑实用的场合,比如有一个类 A,A有个方法f不能再后台执行,需要跑到前台,怎么办呢,上代码:

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. FunctionTransfer::execinmain([this](){this->f();});  

    作为参数的lamda表达式捕获了类A的this指针,然后转换为C++的函数对象,然后跑到前台去执行了,执行完成后才会返回,是不是灰常简洁。

    转载2:http://www.qtcn.org/bbs/read-htm-tid-60505-ds-1-page-1.html#172183 点击打开链接

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. #pragma once  
    2. #include <qthread.h>  
    3. #include <functional>  
    4.   
    5. class QIoService : QObject  
    6. {  
    7. public:  
    8.     QIoService(bool startinthread)  
    9.     {  
    10.         if(startinthread)  
    11.         {  
    12.             worker=new QThread(NULL);  
    13.             worker->start();  
    14.             this->moveToThread(worker);  
    15.         }  
    16.         else  
    17.         {  
    18.             //this object is created in create thread!!!  
    19.         }  
    20.     }  
    21.   
    22.     void post(std::function<void()> func);  
    23.     void send(std::function<void()> func);  
    24.       
    25.     void post(std::function<void()> func,int ms);  
    26.     void send(std::function<void()> func,int ms);  
    27.       
    28.     virtual bool event ( QEvent * e);  
    29.       
    30. protected:  
    31.     QThread *worker;  
    32. };  
    33.   
    34.   
    35. //this should run in mainthread  
    36. extern QIoService *main_ioservice;  
    37.   
    38.   
    39.   
    40. #include "stdafx.h"  
    41. #include "qioservice.h"  
    42. #include <qapplication.h>  
    43. #include <qtconcurrentrun.h>  
    44.   
    45. QIoService *main_ioservice=NULL;  
    46.   
    47. class FunctionEvent : public QEvent  
    48. {  
    49. public:  
    50.     static const QEvent::Type myType = static_cast<QEvent::Type>(2000);  
    51.     FunctionEvent(std::function<void()> f)  
    52.         :QEvent(myType)  
    53.     {  
    54.         func=f;  
    55.     }  
    56.       
    57.     ~FunctionEvent()  
    58.     {  
    59.         //这个他会自动删除  
    60.     }  
    61.   
    62.     std::function<void()> func;  
    63.       
    64. };  
    65.   
    66. void QIoService::post(std::function<void()> func)  
    67. {  
    68.     QApplication::instance()->postEvent(this,new FunctionEvent(func));  
    69. }  
    70.   
    71. void QIoService::send(std::function<void()> func)  
    72. {  
    73.      QApplication::instance()->sendEvent(this,new FunctionEvent(func));  
    74. }  
    75.   
    76. void QIoService::post(std::function<void()> func,int ms)  
    77. {  
    78.     auto lam = [&]()  
    79.     {  
    80.         QThread::currentThread()->wait(ms);  
    81.         post(func);  
    82.     };  
    83.     QtConcurrent::run(lam);  
    84. }  
    85.   
    86. void QIoService::send(std::function<void()> func,int ms)  
    87. {  
    88.     auto lam = [&]()  
    89.     {  
    90.         QThread::currentThread()->wait(ms);  
    91.         send(func);  
    92.     };  
    93.     QtConcurrent::run(lam);    
    94. }  
    95.   
    96. bool QIoService::event ( QEvent * e)  
    97. {  
    98.     if(e->type()==FunctionEvent::myType)  
    99.     {  
    100.         FunctionEvent *fe=(FunctionEvent *)e;  
    101.         fe->func();  
    102.         return true;  
    103.         //这个他会自动删除,不用我们自己手工delete  
    104.     }  
    105.     return false;  
    106. }  

    注解:

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //比如你在另外一个线程,你收到数据,想修改界面。就弄个全局变量  
    2. QIoService g_ui_ios(false);  
    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //你只要  
    2. g_ui_ios.send([你的变量]  
    3. {  
    4.    //修改界面数据,这个会在主线程执行  
    5. });  
    6.   
    7. //如果你是想写个任务队列,  
    8. QIoService g_worker_ios(true);  
    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //你要把某段事情丢到其他线程执行,就  
    2. g_worker_ios.send([]  
    3. {  
    4.   //这段会在其他线程执行。  
    5.   如果执行完了,又想在主线程执行某段,这里可以继续  
    6.   //g_ui_ios.send([]  
    7.   {  
    8.     //这段会在主线程执行  
    9.   });  
    10. });  



    三、更新

    2016年8月27日 第一次更新

    http://blog.csdn.net/qq2399431200/article/details/52335517

  • 相关阅读:
    Linux查看密码
    zabbix 邮件报警配置
    Linux 修改zabbix server的web访问端口
    Zabbix 配置监控主机
    Linux 安装zabbix
    Json解析注解 ---@SerializedName
    IntelliJ IDEA 设置背景图片
    @Override is not allowed when implementing interface method
    nginx ------反向代理和负载均衡
    IntelliJ IDEA 性能优化
  • 原文地址:https://www.cnblogs.com/findumars/p/6568635.html
Copyright © 2011-2022 走看看