本页内容

Qt 中的多线程技术

Qt 提供了许多用于处理线程的类和函数。下面介绍了 Qt 程序员可用于实现多线程应用程序的四种不同方法。

QThread:带可选事件循环的低级 API

QThread 是 Qt 中所有线程控制的基础。每个QThread 实例代表并控制一个线程。

QThread QThread 既可以直接实例化,也可以通过子类化实现。实例化 会提供一个并行事件循环,允许在辅助线程中调用 中的槽函数。通过子类化 ,应用程序可以在启动其事件循环之前初始化新线程,或者在不使用事件循环的情况下运行并行代码。QObject QThread

有关如何使用QThread 的示例,请参阅QThread class reference 以及多线程示例。

QThreadPool 和 QRunnable:线程复用

频繁创建和销毁线程可能会消耗大量资源。为减少这种开销,可以将现有线程重用于新任务。QThreadPool 是一个可重用的 QThread 集合。

要在QThreadPool 的某个线程中运行代码,请重写QRunnable::run() 方法,并实例化子类QRunnable 。使用QThreadPool::start() 将QRunnable 放入QThreadPool 的运行队列中。当有线程可用时,QRunnable::run() 中的代码将在该线程中执行。

每个 Qt 应用程序都有一个全局线程池,可通过QThreadPool::globalInstance() 访问。该全局线程池会根据 CPU 的核心数自动维持最佳的线程数量。不过,也可以显式地创建并管理一个独立的QThreadPool 。

Qt Concurrent: 使用高级 API

该 Qt Concurrent 模块提供了处理一些常见并行计算模式的高级函数:map、filter 和 reduce。与使用QThread 和QRunnable 不同,这些函数完全不需要使用互斥锁或信号量等低级线程原语。 取而代之的是,它们会返回一个QFuture 对象,该对象可在计算结果准备就绪时用于获取结果。QFuture 还可以用于查询计算进度,以及暂停/恢复/取消计算。为了方便起见,QFutureWatcher 支持通过信号和插槽与QFuture进行交互。

Qt Concurrent的 map、filter 和 reduce 算法会自动将计算任务分布到所有可用的处理器核心上,因此今天编写的应用程序在将来部署到核心数量更多的系统时,仍能保持良好的可扩展性。

该模块还提供了 `QtConcurrent::run()` 函数,可在另一个线程中运行任意函数。不过,`QtConcurrent::run()` 仅支持 `map`、`filter` 和 `reduce` 函数所提供功能的一小部分。QFuture 可用于获取函数的返回值,并检查线程是否正在运行。但调用QtConcurrent::run()时仅使用一个线程,无法暂停/恢复/取消,也无法查询其进度。

有关各函数的详细信息,请参阅 Qt Concurrent 模块文档以了解各个函数的详细信息。

WorkerScript:QML 中的多线程

WorkerScript QML 类型允许 JavaScript 代码与 GUI 线程并行运行。

每个WorkerScript 实例可以关联一个.js 脚本。调用WorkerScript.sendMessage() 时,该脚本将在一个单独的线程(以及一个单独的QML context )中运行。当脚本运行完毕时,它可以将响应发送回 GUI 线程,从而触发WorkerScript.onMessage() 信号处理程序。

使用WorkerScript 的方式类似于使用已被移至另一个线程的 workerQObject 。数据通过信号在线程之间传输。

有关如何实现脚本以及可在线程间传递的数据类型列表的详细信息,请参阅WorkerScript 文档。

选择合适的方法

如上所述,Qt 为开发多线程应用程序提供了多种解决方案。针对特定应用程序的正确解决方案取决于新线程的用途及其生命周期。下文将对比 Qt 的多线程技术,并针对一些示例用例提供推荐的解决方案。

解决方案对比

特性QThreadQRunnable 和QThreadPoolQtConcurrent::run()Qt Concurrent (Map、Filter、Reduce)WorkerScript
语言C++C++C++C++QML
可以指定线程优先级是是
线程可以运行事件循环是
线程可通过信号接收数据更新是(由工作线程QObject 接收)是(由WorkerScript 接收)
线程可通过信号进行控制是(由QThread 接收)是(由QFutureWatcher 接收)
可以通过QFuture部分是
内置暂停/恢复/取消功能是

示例用例

线程的生命周期操作解决方案
单次调用在另一个线程中运行一个新的线性函数,运行期间可选地更新进度。Qt 提供了不同的解决方案:
单次调用在另一个线程中运行现有函数并获取其返回值。使用QtConcurrent::run() 运行该函数。当函数返回时,让QFutureWatcher 发出finished() 信号,并调用QFutureWatcher::result() 获取该函数的返回值。
单次调用利用所有可用核心,对容器中的所有项目执行操作。例如,从一组图像中生成缩略图。使用Qt Concurrent 的QtConcurrent::filter()函数选择容器元素,并使用QtConcurrent::map()函数对每个元素应用操作。若要将输出折叠为单一结果,请改用QtConcurrent::filteredReduced()和QtConcurrent::mappedReduced()。
单次调用/持久化在纯 QML 应用程序中执行长时间计算,并在结果准备就绪时更新 GUI。将计算代码放置在.js 脚本中,并将其附加到WorkerScript 实例上。调用WorkerScript.sendMessage()在新的线程中启动计算。让脚本也调用sendMessage(),将结果传递回GUI线程。在onMessage 中处理结果,并在那里更新GUI。
持久化在另一个线程中创建一个对象,该对象可在请求时执行不同任务,和/或接收新数据进行处理。继承 `QObject ` 类以创建一个工作线程。实例化该工作线程对象以及一个 `QThread`。将工作线程移至新线程中。通过队列式信号-槽连接向工作线程对象发送命令或数据。
永久在另一个线程中反复执行一项耗时操作,该线程无需接收任何信号或事件。在QThread::run()的重写版本中直接编写无限循环。在不使用事件循环的情况下启动该线程。让该线程发出信号,将数据发回给GUI线程。

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.