一、目录

转载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++标准库中大名鼎鼎的函数对象。

  1. class FunctionTransfer : public QObject
  2. {
  3. Q_OBJECT
  4. public:
  5. ///@brief 构造函数
  6. explicit FunctionTransfer(QObject *parent = 0);
  7. public:
  8. ///@brief 制定函数f在main中执行
  9. static void execinmain(std::tr1::function<void()> f);
  10. signals:
  11. ///@brief 在别的线程有函数对象传来
  12. void comming(std::tr1::function<void()> f);
  13. public slots:
  14. ///@brief 执行函数对象
  15. void exec(std::tr1::function<void()> f);
  16. };

然后是源文件:

  1. //在全局数据区实例化一个FunctionTransfer的实例,该实例所在的县城就是主线程。
  2. FunctionTransfer main_thread_forward;
  3. void FunctionTransfer::execinmain(std::tr1::function<void()> f)
  4. {
  5. main_thread_forward.exec(f);
  6. }
  7. FunctionTransfer::FunctionTransfer(QObject *parent) :
  8. QObject(parent)
  9. {
  10. connect(this,SIGNAL(comming(std::tr1::function<void()>)),this,SLOT(exec(std::tr1::function<void()>)),Qt::BlockingQueuedConnection);
  11. }
  12. void FunctionTransfer::exec(std::tr1::function<void()> f)
  13. {
  14. if(Gt::isMainThread())
  15. {
  16. f();
  17. }
  18. else
  19. {
  20. emit this->comming(f);
  21. }
  22. }

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

  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 点击打开链接

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

注解:

  1. //比如你在另外一个线程,你收到数据,想修改界面。就弄个全局变量
  2. QIoService g_ui_ios(false);
  1. //你只要
  2. g_ui_ios.send([你的变量]
  3. {
  4. //修改界面数据,这个会在主线程执行
  5. });
  6. //如果你是想写个任务队列,
  7. QIoService g_worker_ios(true);
  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

Qt 跨UI线程的数据交换和信号-槽调用实现方案汇总的更多相关文章

  1. [转]QT子线程与主线程的信号槽通信-亲测可用!

    近用QT做一个服务器,众所周知,QT的主线程必须保持畅通,才能刷新UI.所以,网络通信端采用新开线程的方式.在涉及到使用子线程更新Ui上的控件时遇到了点儿麻烦.网上提供了很多同一线程不同类间采用信号槽 ...

  2. Disruptor——一种可替代有界队列完成并发线程间数据交换的高性能解决方案

    本文翻译自LMAX关于Disruptor的论文,同时加上一些自己的理解和标注.Disruptor是一个高效的线程间交换数据的基础组件,它使用栅栏(barrier)+序号(Sequencing)机制协调 ...

  3. Exchanger实现线程间数据交换

    package com.duchong.concurrent; import java.util.ArrayList; import java.util.List; import java.util. ...

  4. 详解 Qt 线程间共享数据(用信号槽方式)

    使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的. Qt 线程间共享数据是本文介绍的内容,多的不说,先来啃内容.Qt线程间共享 ...

  5. Qt学习:线程间共享数据(使用信号槽传递数据,必须提前使用qRegisterMetaType来注册参数的类型)

    Qt线程间共享数据主要有两种方式: 使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的: 使用singal/slot机制,把数据 ...

  6. moveToThread的最简单用法(依葫芦画瓢即可)(使得线程也更偏向于信号槽的使用方法)

    /*! * \file main.cpp * * Copyright (C) 2010, dbzhang800 * All rights reserved. * */ #include <QtC ...

  7. WPF / Win Form:多线程去修改或访问UI线程数据的方法( winform 跨线程访问UI控件 )

    WPF:谈谈各种多线程去修改或访问UI线程数据的方法http://www.cnblogs.com/mgen/archive/2012/03/10/2389509.html 子线程非法访问UI线程的数据 ...

  8. Qt5中运行后台网络读取线程与主UI线程互交

    项目中有一个需求就是,因为需要请求服务端数据,因为网络的读取会阻塞,所以该过程不能放在Qt中的UI主线程当中,需要用一个后台线程来读取数据,数据准备完毕后 在通过Qt5中的信号槽机制来跨线程的传递数据 ...

  9. c#多线程(UI线程,控件显示更新) Invoke和BeginInvoke 区别

    如果只是直接使用子线程访问UI控件,直接看内容三,如果想深入了解从内容一看起. 一.Control.Invoke和BeginInvoke方法的区别 先上总结: Control.Invoke 方法 (D ...

随机推荐

  1. 学习web开发遇到几个细节问题

    1.在jsp中使用jsp表达式在input标签中时,避免直接和结束"/"相连 2.提取input select 标签内的内容,使用...value提取其值 3.form中含有一个o ...

  2. 【codeforces 785C】Anton and Fairy Tale

    [题目链接]:http://codeforces.com/contest/785/problem/C [题意] 容量为n的谷仓,每一天都会有m个谷子入仓(满了就视为m);第i天 会有i只鸟叼走i个谷子 ...

  3. spring-boot-sample-web-jsp

    Pom文件需要配置的: <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl&l ...

  4. poj 3071 可能DP

    http://poj.org/problem? id=3071 推方程不难,可是难在怎么算 dp[i][j]表示第i场时第j仅仅队伍存活下来的概率 方程:dp[i][j]=sigma(dp[i-1][ ...

  5. dwc_otg驱动 "BUG: sleeping function called from invalid context at mm/page_alloc.c"

    方案商的开发板上otg功能只能做device,硬件看过后说没有5v供电,加上后能够识别U盘了,但是内核报了错 [ 3.264000] usb 2-1: new high-speed USB devic ...

  6. HTTP协议(一些报头字段的作用,如cace-control、keep-alive)

    ---恢复内容开始--- Http连接是一种短连接,是一种无状态的连接. 所谓的无状态,是指浏览器每次向服务器发起请求的时候,不是通过一个连接,而是每次都建立一个新的连接. 如果是一个连接的话,服务器 ...

  7. 1 WCF 一个基础理论 以及如何实现一个简单wcf服务

    1 SOA : service oriented architecture 面向服务的架构 2 web service标准 3 概念理解图 4 WCF类库 项目的 wcf简单实现 首先创建一个简单的w ...

  8. 编程军规 —— Java 篇

    提高代码的可读性,规避容易出现的错误. 0. 共性 对象或引用的非空性判断: 强制类型转换时: 函数返回时: 函数的输入参数: 任务执行的成功或失败判断: 文件打开:网络连接:数据库连接: 内存申请: ...

  9. 详解Python模块导入方法

    python常被昵称为胶水语言,它能很轻松的把用其他语言制作的各种模块(尤其是C/C++)轻松联结在一起.python包含子目录中的模块方法比较简单,关键是能够在sys.path里面找到通向模块文件的 ...

  10. duilib拖动控制功能的实现(源代码)

    转载请注明原始出处.谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/41144283 duilib库中原本没有显示的对控件添加拖拽的功能.而实 ...