两种方法:
- 继承QThread类,重写run方法(QT4.8之前使用)
- 自定义一个继承QObject的类转移到Thread中。(和线程的交互通过信号和槽(实际上其实是通过事件)联系,QT4.8之后,官方建议这种方法)
为什么使用线程:?
举个例子:如果我们在写GUI程序的时候,如果某处的数据,计算比较复杂,当前主线程就会卡在这里,在具体表现就是界面会卡住。所以在这个时候多线程就起到了关键的作用, 我们将复杂的逻辑运算交给线程,由线程在后台处理。(注意:线程不能操作图形界面,他的线程任务是在后天进行数据运算等。)
使用方法一的步骤:
- 创建线程类,继承QThread
- 重写run函数(尽量把复杂的逻辑,计算放在run函数中。)
- 主线程中创建线程对象,调用start函数启动线程
(只有run函数在新线程中,其余都在主线程内)
方法二:
QObject是Qt框架的基本类,但凡涉及到信号槽有关的类都是继承于QObject。QObject是一个功能异常强大的类,它提供了Qt关键技术信号和槽的支持以及事件系统的支持,同时它提供了线程操作的接口,也就是QObject是可以选择不同的线程里执行的。
QObject的线程转移函数是:void moveToThread(QThread * targetThread) ,通过此函数可以把一个顶层Object(就是没有父级)转移到一个新的线程里。
用QObject来实现多线程有个非常好的优点,就是默认就支持事件循环(Qt的许多非GUI类也需要事件循环支持,如QTimer、QTcpSocket),QThread要支持事件循环需要在QThread::run()中调用QThread::exec()来提供对消息循环的支持,否则那些需要事件循环支持的类都不能正常发送信号,因此如果要使用信号和槽,那就直接使用QObject来实现多线程。
使用QObject创建多线程的方法如下:
- 写一个继承QObject的类,对需要进行复杂耗时逻辑的入口函数声明为槽函数
此类在旧线程new出来,不能给它设置任何父对象。 - 同时声明一个QThread对象,在官方例子里,QThread并没有new出来,这样在析构时就需要调用QThread::wait(),如果是堆分配的话, 可以通过deleteLater来让线程自杀
- 把obj通过moveToThread方法转移到新线程中,此时object已经是在线程中了
把线程的finished信号和object的deleteLater槽连接,这个信号槽必须连接,否则会内存泄漏 - 正常连接其他信号和槽(在连接信号槽之前调用moveToThread,不需要处理connect的第五个参数,否则就显示声明用Qt::QueuedConnection来连接)
初始化完后调用’QThread::start()'来启动线程. - 在逻辑结束后,调用QThread::quit退出线程的事件循环