QThread多线程编程经典案例分析(三种方法,解释了为什么使用moveToThread的根本原因,即为了避免调用QThread::exec() )
传统的图形界面应用程序都只有一个线程执行,并且一次执行一个操作。如果用户调用一个比较耗时的操作,就会冻结界面响应。
一个解决方法是按照事件处理的思路:
调用 Void QApplication::processEvents() 或 void QApplication::processEvents ( int maxtime ) 来强迫事件循环进行,但是这种做法是有潜在风险的。按照QCoreApplication:processEvents()可能会引起递归,导致栈溢出崩溃的说法,当主线程在某个槽函数里正在执行processEvents时, 刚好有一个能响应此槽函数的信号发送过(肯定是其他线程发的信号), 这时就可能会发生可怕的递归, 导致栈溢出崩溃。 原因是processEvents在处理自己槽函数的事件时,又会调用到processEvents,进入到无尽的递归中。
另外一个解决方法是:采用多线程。、
QT QThread多线程编程的方法一直有个争议,就是Bradley T. Hughes:You’re doing it wrong 归纳为3中方法优劣问题:
方法(1):
1. 不使用事件循环。这是官方的 Manual 、example 以及相关书籍中都介绍的一种的方法。
a. 子类化 QThread
b. 重载 run 函数,run函数内有一个 while 或 for 的死循环
c. 设置一个标记为来控制死循环的退出。这里的run函数自己执行了一个循环,不需要事件循环机制了。
方法(2):
这种方法也是Bradley T. Hughes极力批判的 a. 子类化 QThread, b. 重载 run 使其调用 QThread::exec() c. 并为该类定义信号和槽,这样一来,由于槽函数并不会在新开的 thread 运行,很多人为了解决这个问题在构造函数中调用 moveToThread(this);
而争论和不解正是这样的一条语句造成的。
Bradley T. Hughes 给出说明是: QThread 应该被看做是操作系统线程的接口或控制点,而不应该包含需要在新线程中运行的代码。需要运行的代码应该放到一个QObject的子类中,然后将该子类的对象moveToThread到新线程中。
方法(3):
在Qt4.3(包括)之前,run 是虚函数,必须子类化QThread来实现run函数。而从Qt4.4开始,qthreads-no-longer-abstract ,run 默认调用 QThread::exec() 。这样一来不需要子类化 QThread 了,只需要子类化一个 QObject 就够了,这正是被 Bradley T. Hughes推荐的方法。方法如下
QThread thread;
Object obj;
Dummy dummy;
obj.moveToThread(&thread);
QObject::connect(&dummy, SIGNAL(sig()), &obj, SLOT(slot()));
thread.start();
所以,方法(1)和方法(3)是正确的QT QThread多线程编程方法,方法(2)用的最多,但只是三人成虎,一种不恰当的用法
http://blog.csdn.net/bladeandmaster88/article/details/51802491
最新文章
- 使用Django建立网站
- Django-简单项目创建
- ON DUPLICATE KEY UPDATE
- 42. Subsets &;&; Subsets II
- (转)SpringSecurity扩展User类,获取Session
- struts中拦截器的开发
- java读取大容量excel之二(空格、空值问题)
- [C# 网络编程系列]专题六:UDP编程
- MiniUI学习笔记1
- 家庭版Windows10没有远程桌面的问题
- linux bash shell:最方便的字符串大小写转换(lowercase/uppercase conversion) (转)
- 在win10 64位系统安装 lxml (Python 3.5)
- Springboot中如何在Utils类中使用@Autowired注入bean
- Mysql 用户权限管理
- GZIPOutputStream GZIPInputStream
- iOS第三方登录qq
- Nexus6p:正在下载系统更新,没有进度
- cobbler配置解析
- NOIp2018提高组游记
- Oracle VirtualBox 问题汇总
热门文章
- M创aterial Design作风Android申请书--创建列表和卡
- iOS项目double、float精度丢失解决办法
- 编译和使用jasper库的一个注意事项
- vue-router设置页面标题
- 开发Android项目中使用androidannotations
- UVA - 10312 Expression Bracketing
- P和P1指向了O和O1两个变量(对象)的地址, 而不是O和O1的内容(对象的实际地址)——充分证明@是取变量(对象)的地址,而不是变量里面的内容,够清楚!
- 将指定路径下的所有SVG文件导出成PNG等格式的图片(缩略图或原图大小)
- cefsharp 与webbrowser简单对比概述
- 使用HANDLE_MSG宏简化Win32应用的开发