Qt线程使用杂谈

注:此文不涉及Qt线程使用的具体代码例子,如果是怎么使用Qt线程,见下面链接。

现在写一个项目并行和多线程几乎是必用的。在Qt中最多的是用QThread,只是QThread有两种用法,继承与QObject::moveToThread函数。在群里有人郁闷Qthread的用法,此文写下个人简单的见解。

首先简单说下QThread的这两种用法:

1.继承QThread使用方法:

继承QThread类,实现其run()函数,那么run函数里的都是在新线程调用。

2.QObject::moveToThread:

一个类继承QObject,然后使用QObject::moveToThread(QThread *)函数,把这个类移动到新的线程中去,然后与主线程全部通过信号槽Qt::QueuedConnection或者Qt::BlockingQueuedConnection(阻塞调用线程,槽函数执行完毕才继续执行)进行信号槽链接进行线程间通讯,那么信号触发的槽是在新的线程执行的,同样新线程的信号链接的主线程的槽,也是在主线程执行的。但是直接调用函数和Qt::DirectConnection链接信号槽的槽函数,是会在直接调用的函数和信号发出的线程中执行的。对于Qt::AutoConnection(Qt默认的链接方式)链接的信号槽,如果在一个线程就是Qt::DirectConnection,不在一个线程就是Qt::QueuedConnection。

注:movetothread底层是依赖Qt时间循环实现的(QCoreApplication::postEvent),所以使用movetothread必须是在开启Qt事件循环的程序中,就是main函数中调用QCoreApplication::exec的程序。

 

技术都是为业务服务的,同样多线程我们使用也是为了解决场景问题的,如果你只是为了多线程而多线程,那么本文对您已经结束了。

首先假设都是在Qt程序中(即基于Qt事件循环的程序中)。然后按照个人使用过场景来说下个人以为的Qt线程的使用方式。

1.耗时的一次计算,I/O或者初始化:

不建议使用QThread,建议使用:QRunnable和QThreadPool结合使用或者直接,QtConcurrent::run

2.周期性的耗时计算或I/O:

使用继承QObject和moveToThread函数的方式,封装到类中,然后后台线程启动驻留,然后信号槽传送计算参数和接收计算的数据。

3.程序线程分模块,例如网络和数据库单独在一个线程或者分别的线程设计:

使用继承Qobject和moveToThread函数的方式,封装到类中,然后后台线程启动驻留,然后信号槽传送操作命令和取回结果。(注QWidget的UI操作只能在主线程的)。

4.多个任务执行者,分别的执行,一个调度者:

每个封装一个类,然后执行者和调度者分线程,数个或者单个执行者一个线程,通过信号槽与调度者交互,用moveToThread方式分线程。

5.程序中引用其他库,其他库且有独立的事件循环:

用继承QThread的方式,在run中启用其他库的事件循环,需要与主线程交互的部分采用自定义事件和QCoreApplication::postEvent方式通讯。(下面链接:QAsioTcpSocket)。

一般的能用到线程的场景,我也就使用过和想到这么多。其中:

周期性的小任务(几乎不耗时的)使用定时器,用到线程的。
Qt中的网络访问:Qt的网络接口都是默认异步的,异步就没有等待只说,也就用不到线程,所以不是为了划分模块不建议单独线程的。当然你要强制全同步访问另算(不感觉同步优势,自定义状态机就解决异步调度的问题了啊?)。

 

附:

1.Qt线程使用的教程:

Qt学习之路2:其中71到75是讲线程的使用

2.我的项目中使用Qthread的例子:

QTcpServer多线程实现 这篇文章提到的QthreadTcpserver

QAsioTcpSocket 目的是把asio封装一个与Qt结合的版本,替代低效QTcpServer。

《Qt线程使用杂谈》有6个想法

  1. 有两个人,其中一个脸上崎岖不平,另一个人对他说:你知道吗,苍蝇不敢落在你的脸上哎!
    他很纳闷,问:为什么呢?
    呵呵,怕崴脚。
    如果这样说,苍蝇也不敢落在你的脸上啊!
    哦?
    因为你的脸太滑了!它怕匹叉! http://url.cn/XfB45g

发表评论

电子邮件地址不会被公开。 必填项已用*标注