Qt之线程的使用

多线程编程是一种常见的技术,它可以提高程序的性能和响应性。Qt 是一个广泛使用的跨平台 C++ 图形用户界面(GUI)库,它提供了方便的线程支持。在本文中,我们将探讨 Qt 线程的使用,并通过示例来展示如何在 Qt 应用程序中创建和管理线程。

首先,让我们了解一下线程的基本概念。线程是程序执行的独立路径,每个线程可以同时执行不同的任务。通过创建多个线程,我们可以并行处理多个任务,从而提高程序的执行效率。

在 Qt 中,可以使用QThread类来创建和管理线程。以下是一个简单的示例,展示了如何在 Qt 中使用线程:

#include <QThread>
#include <QDebug>

// 要在线程中执行的任务函数
void taskFunction() {
    qDebug() << "Task running in thread";
}

int main() {
    // 创建一个新线程
    QThread thread;
    // 在新线程中执行任务函数
    QObject::connect(&thread, &QThread::started, []() {
        taskFunction();
    });
    
    thread.start();
    
    // 等待线程执行完成
    thread.waitForFinished();
    return 0;
}

在上述示例中,我们创建了一个QThread对象thread。然后,我们使用connect函数将QThread::started信号与一个匿名函数连接起来,该函数会在线程启动后执行taskFunction

接下来,我们使用start函数启动线程,线程将开始执行taskFunction

最后,我们使用waitForFinished函数等待线程执行完成。

请注意,在实际应用中,你可能需要在线程中处理更复杂的任务,并在适当的时候进行线程间的通信和同步。此外,还可以使用QMutexQSemaphore等同步对象来保护共享数据的访问。

另外,线程的创建和管理也需要谨慎处理。过度创建线程可能会导致系统资源的消耗和性能下降。在实际应用中,需要根据任务的特性和需求来合理规划线程的数量和使用方式。

除了手动创建线程,Qt 还提供了一些更高级的线程管理工具,例如QThreadPoolQtConcurrentQThreadPool可以方便地管理一组线程,并将任务分配到空闲的线程中执行。QtConcurrent提供了一些简化的并行计算接口,使得编写多线程代码更加简单和高效。

使用 QThreadPool::globalInstance() 线程池操作

QThreadPool用于管理和回收单个QThread对象,以帮助减少使用线程的程序中的线程创建成本。每个Qt应用程序都有一个全局QThreadPool对象,可以通过调用globalInstance()进行访问。

class Task : public QRunnable
{
    void run() override
    {
        // 费时操作
        qDebug() << "thread run at:" << QThread::currentThread();
    }
};
 
auto *task = new Task();
QThreadPool::globalInstance()->start(task);

注意事项:

  • 默认情况下, 用户在调用 QThreadPool::globalInstance()->start(task); 之后不需要再关心 task 对象的释放问题,因为 QThreadPool 会自动删除 task。当然也可以通过 QRunnable :: setAutoDelete(bool) 调整策略。

  • 在一定时间内未使用的线程将过期。默认的到期超时为30000毫秒(30秒)。可以使用setExpiryTimeout()进行调整。当设置到期超时为负值时将禁用到期机制。

  • maxThreadCount()方法可以查询最大线程数,也可以使用setMaxThreadCount()进行调整。默认的maxThreadCount()QThread::idealThreadCount()

  • QThreadPool 是一个用于管理线程的低级类,高级玩法请参照 QtConcurrent 模块。

QtConcurrent模块。(高级玩法)

QtConcurrent模块扩展了Qt Core模块中提供的基本线程支持,并简化了可在所有可用CPU内核上并行执行的代码的开发。 The QtConcurrent namespace provides high-level APIs that make it possible to write multi-threaded programs without using low-level threading primitives such as mutexes, read-write locks, wait conditions, or semaphores. Programs written with QtConcurrent automatically adjust the number of threads used according to the number of processor cores available. This means that applications written today will continue to scale when deployed on multi-core systems in the future.

此模块简化了用户操作,强烈推荐使用。

下面是一个简单的示例。

// 方法参数为 Function 
// 可以处理返回值
QFuture<int> res = QtConcurrent::run([](){ 
    // 费时操作
    return 0;
});
 
// 可以等待处理完成
// 1.阻塞执行 不阻塞事件循环
// while(!res.isFinished()) {
    // wait
    // QApplication::processEvents(QEventLoop::AllEvents, 200);
// }
// 2. 阻塞等待
res.waitForFinished();
 
// 处理返回值
int result = res.result();

注意事项:

  • 需要引入 Qt Concurrent模块。

  • 可以使用 QFutureWatcher 监视 QFuture。以下是一个官方示例:

    // Instantiate the objects and connect to the finished signal.
    MyClass myObject;
    QFutureWatcher<int> watcher;
    connect(&watcher, QFutureWatcher<int>::finished, &myObject, &MyClass::handleFinished);

    // Start the computation.
    QFuture<int> future = QtConcurrent::run(...);
    watcher.setFuture(future);

码字不易,欢迎点赞支持!

相关推荐
Mr.Q3 分钟前
OpenCV和Qt坐标系不一致问题
qt·opencv
时光の尘14 分钟前
C语言菜鸟入门·关键字·float以及double的用法
运维·服务器·c语言·开发语言·stm32·单片机·c
我们的五年19 分钟前
【Linux课程学习】:进程描述---PCB(Process Control Block)
linux·运维·c++
以后不吃煲仔饭28 分钟前
Java基础夯实——2.7 线程上下文切换
java·开发语言
进阶的架构师29 分钟前
2024年Java面试题及答案整理(1000+面试题附答案解析)
java·开发语言
前端拾光者33 分钟前
利用D3.js实现数据可视化的简单示例
开发语言·javascript·信息可视化
程序猿阿伟35 分钟前
《C++ 实现区块链:区块时间戳的存储与验证机制解析》
开发语言·c++·区块链
傻啦嘿哟1 小时前
如何使用 Python 开发一个简单的文本数据转换为 Excel 工具
开发语言·python·excel
大数据编程之光1 小时前
Flink Standalone集群模式安装部署全攻略
java·大数据·开发语言·面试·flink
初九之潜龙勿用1 小时前
C#校验画布签名图片是否为空白
开发语言·ui·c#·.net