使用QtConcurrent小结

本文探讨了QtConcurrent库中的run方法特性,通过不同测试案例分析了线程的内存占用情况,证实了线程在循环中能自动回收,适合在Qt应用中高效管理并发任务。

首先查看QtConcurrent在使用时候的官方注释如下:

使用其做法是在qmake文件中添加并且在使用时头文件也进行添加。

常用的run方法注释如下:

 

意味着该函数返回一个单独的线程,该线程是从线程池中取得的,既然是从线程池中取得的线程意味着可能并不能立即执行,

只有当这个线程可获得时才进行执行,该线程不支持取消,停止或者进度显示,返回值只可以在正在执行或者完成状态是返回。那么现在问题来了,如果将该线程多次执行,放入循环中,该线程会自动进行回收工作吗?

以下就是见证奇迹的时刻了。

首先是测试程序在运行起来不做任何操作的程序大小

测试代码如下:

 QString str = "canshu";
 for( int index = 0; index < 1000000; ++ index )
 {
 }

在资源管理器中内存占用为:

其次是测试在程序不使用线程只进行printf

测试代码如下:

QString str = "canshu"; for( int index = 0; index < 1000000; ++ index ) { outPut(); }

在程序运行过程中,此时没有绘制mainwindow窗口时,内存为如下图所示:

程序运行结束后,占用内存同没有进行任何操作一样内存占用。

本次测试使用线程进行调用输出函数

测试代码如下:

QString str = "canshu"; 
for( int index = 0; index < 1000000; ++ index )
{ 
    QtConcurrent::run(this,&MainWindow::outPut); 
}

程序运行结束后,资源管理器截图如图所示:

证明使用线程确实造成了内存占用过高的问题。

以下对比一下使用参数和不使用参数传递的效果。

使用参数进行测试的代码如下:

QString str = "canshu";
for( int index = 0; index < 1000000; ++ index ) 
{ 
    QtConcurrent::run(this,&MainWindow::outPutWithArg,str); 
}

资源管理器中内存截图如图所示:

 

此结果为最终结果,在运行过程中出现过内存激增的情况,但最后降下来结果如上图。

最后进行一个小测试

测试代码如下:

QString str = "canshu"; 
for( int index = 0; index < 1000000; ++ index ) 
{ 
    outPutWithArg(str); 
}

资源管理器中截图如下:

在最终似乎由于循环次数较多,导致输出没有输出正常。

因此,该线程是自带销毁的,可以在循环中放心使用。

 

### 在 Qt 中使用 `QtConcurrent` 执行异步任务 `QtConcurrent` 是 Qt 提供的一个用于简化多线程编程的模块,它允许开发者在不直接操作线程的情况下执行异步任务。通过 `QtConcurrent::run()`,可以将一个函数提交到线程池中异步执行[^1]。 #### 基本示例 以下是一个使用 `QtConcurrent::run()` 执行异步任务的简单示例: ```cpp #include <QCoreApplication> #include <QtConcurrent/QtConcurrentRun> #include <QDebug> #include <QFutureWatcher> void asyncTask() { qDebug() << "Task is running in background thread..."; QThread::sleep(2); // 模拟耗时操作 qDebug() << "Task completed."; } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QFutureWatcher<void> watcher; QObject::connect(&watcher, &QFutureWatcher<void>::finished, [&]() { qDebug() << "Async task has finished."; app.quit(); }); QFuture<void> future = QtConcurrent::run(asyncTask); watcher.setFuture(future); return app.exec(); } ``` 在该示例中,`asyncTask` 函数将在后台线程中执行,主线程通过 `QFutureWatcher` 监听任务完成状态,并在任务完成后退出应用[^1]。 #### 获取返回值 如果异步任务需要返回结果,可以定义一个具有返回值的函数,并通过 `QFuture` 获取结果: ```cpp #include <QCoreApplication> #include <QtConcurrent/QtConcurrentRun> #include <QDebug> #include <QFutureWatcher> int computeResult() { QThread::sleep(1); return 42; } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QFutureWatcher<int> watcher; QObject::connect(&watcher, &QFutureWatcher<int>::finished, [&]() { qDebug() << "Result is:" << watcher.result(); app.quit(); }); QFuture<int> future = QtConcurrent::run(computeResult); watcher.setFuture(future); return app.exec(); } ``` 该示例中,`computeResult()` 返回一个整型值,`QFutureWatcher<int>` 用于监听异步任务完成,并通过 `watcher.result()` 获取最终结果。 #### 取消异步任务 如果希望在任务执行过程中取消它,可以调用 `QFuture::cancel()` 方法。但需要注意的是,任务是否能被取消取决于其实现是否响应取消请求: ```cpp watcher.future().cancel(); ``` 可以在连接的 `finished` 信号处理中检查任务是否被取消: ```cpp QObject::connect(&watcher, &QFutureWatcher<int>::finished, [&]() { if (watcher.isCanceled()) { qDebug() << "Task was canceled."; } else { qDebug() << "Result is:" << watcher.result(); } }); ``` #### 异常处理 如果异步任务中抛出异常,`QFuture` 会捕获并存储该异常信息。可以通过 `QFuture::error()` 和 `QFuture::errorString()` 获取错误信息: ```cpp if (watcher.future().error() != QFuture<void>::NoError) { qDebug() << "Error occurred:" << watcher.future().errorString(); } ``` #### 多任务并行 若需执行多个并行任务,可以使用 `QtConcurrent::map()` 或 `QtConcurrent::mappedReduced()` 来处理容器中的数据。这些方法适用于需要对多个数据项进行并行处理的场景。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值