• 做一个幸福的人,读书,旅行,努力工作,关心身体和心情。
  • 不管有没有人爱,也要努力做一个可爱的人。不埋怨谁,不嘲笑谁,也不羡慕谁,阳光下灿烂,风雨中奔跑,做自己的梦,走自己的路。

QThread 多线程学习笔记

Qt lcq 3年前 (2015-07-01) 785次浏览 0个评论

最近想封装一个网络方面的类给自己以后用。但是Qt提供的网络类以前又不稳定,所以打算将Libcurl进行封装。而Libcurl不是多线程的。但在请求数据的时候,我们是不可能阻塞UI的,所以我需要将Libcurl的一些网络操作封装到一个线程中。各种百度Google一番之后,将学习到的多线程的方法与遇到的坑记录一下,供自己以后查阅。

第一种使用多线程的方法:继承QThread,重写run方法。

代码如下所示。

你只要实例化一个Thread *thread对象,然后调用thread->start()方法,Thread会自动开辟一个线程,运行run方法。

这个需要注意的有如下几点:

1、虽然你继承了QThread,但是只有run()函数中的代码会在新开辟的线程中执行。在run()函数中声明的变量和实例化的对象,都属于新开辟的线程。如上述的代码,假设你实例化一个Thread类,然后调用loop函数,这个时候,你这个Thread是在哪个线程实例化的,就会在哪个线程里面执行,而不是在run()新开辟的线程里面运行。

2、Thread里面的槽函数,也不会在新开辟的线程里面运行。假设你在MainWidget里面实例化了一个Thread对象,此时,假设MainWidget是在线程A里面运行。你将MainWidget里面的信号与Thread里面的槽连接。MainWidget发出信号之后,Thread里面的槽函数依然会在线程A里面运行。所以此时,你可以将Thread实例化的对象看做是普通的类即可。

第二种使用多线程的方法:使用moveToThread方法。

这是大多数人的使用方法。因为QObject::moveToThread方法中的QThread是持续运行的。而且,这样使用之后,当你使用信号槽连接被moveToThread到线程里面的对象的槽函数,都是在新的线程里面执行的。当然需要注意的是,你如果直接调用对象的槽函数,还是会在对象所依附的进程里面执行的。

当然,我一开始的时候,想结合第一种办法跟第二种办法,继承QThread之后,然后调用this->moveToThread(this)。觉得这样就结合了两种方法的有点。这个虽然可以运行,但不被官方推荐。因为在构造函数中moveToThread(),此时Thread还没有开始运行;Thread移动到它自己空间去运行后,我们失去了对MyThread的引用。解决办法去掉this即可。

记录一下我遇到的问题:

1、使用第二种方法,只有将线程调用start()函数之后,所有连接的槽函数才会执行,否则就算你发信号,被moveToThread的对象里面的槽函数也是不会执行的。

2、 BlockUI *blockUI = new BlockUI(name, this);QThread *thread = new QThread();blockUI->moveToThread(thread);这样写会提示:QObject::moveToThread: Cannot move objects with a parent。意思是子对象不能脱离父对象,单独切换到与父对象不同的线程中。

如果你有Github,这是我测试写的代码,可以去Github查看。链接。注意:我只是测试了QThread的一些使用方法,使用完之后,没有对资源等进行释放。代码里面,BlockUI主要是用来阻塞UI的,如果不使用线程,你将会卡住界面。


参考资料:

1、Qt 线程基础(QThread、QtConcurrent等)

2、QObject 之 Thread Affinity

3、QT之深入理解QThread

4、QThread与QWidget使用

5、一种使用QThread线程的新方法QObject::moveToThread

6、QThread的一种用法

7、Qt多线程学习-用例子来理解多线程

8、Qt那点事儿(三) 论父对象与子对象的关系

9、Qt开发者关于QThread的咆哮——你们都用错了


乐趣公园 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明QThread 多线程学习笔记
喜欢 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址