Qt使用QtConcurrent::run实现异步等待和同步调用

 更新时间:2025年09月18日 10:48:49   作者:__ocean  
Qt使用QtConcurrent::run实现C#中类似async await的用法,虽不如C#的async/await灵活,但可满足业务需求并提升代码可读性,下面就来详细的介绍一下QtConcurrent::run实现异步等待和同步调用

在使用Qt进行开发时,经常需要使用异步方法,不同于C#的async/await,Qt中提供了QtConcurrent::run接口方法可供调用,习惯了C#的await,便想着能不能封装几个类似的函数在项目中使用,探索了下,有如下几个方案

首先定义全局线程池

	inline QThreadPool* globalThreadPool() 
	{
		static QThreadPool* pool = []() {
			QThreadPool* p = new QThreadPool;
			p->setMaxThreadCount(QThread::idealThreadCount());
			return p;
			}();
		return pool;
	}

方案一,最简单的封装调用,直接异步调用,无任何返回结果,也不会卡住调用线程:

	auto CallAsync = [](auto func){
		QtConcurrent::run(globalThreadPool(), func);
	};

调用时用法如下:

CallAsync([](){
	// do something in theadpool...
});

方案二,如果我们想在异步执行时,调用线程同步等待,可封装如下:

auto AwaitCallAsync = [](auto func, int timeoutSeconds = 5) -> bool
{        
    QFuture<void> future = QtConcurrent::run(globalThreadPool(), func);
    
    // 使用智能指针管理对象生命周期
    auto watcher = std::make_shared<QFutureWatcher<void>>();
    auto loop = std::make_shared<QEventLoop>();
    auto timer = std::make_shared<QTimer>();
    
    bool timedOut = false;    
    if (timeoutSeconds > 0) {
        timer->setInterval(timeoutSeconds * 1000);
        timer->setSingleShot(true);
        QObject::connect(timer.get(), &QTimer::timeout, [&timedOut, loop]() {
            timedOut = true;
            loop->quit();
        });
        timer->start();
    }    
    QObject::connect(watcher.get(), &QFutureWatcher<void>::finished, loop.get(), &QEventLoop::quit);
    watcher->setFuture(future);    
    loop->exec();
    
    // 清理资源
    if (!timedOut && timeoutSeconds > 0) {
        timer->stop();
    }    
    return !timedOut; // 返回是否正常完成
};

此时,执行AwaitCallAsync时,调用线程会同步等待但并不会卡住线程,为了避免长时间等待,也可以添加超时参数。

方案三,有时,我们在希望在异步函数调用完成后能回到调用线程继续执行,那么可以添加QFutureWatcher,监控异步函数的执行,然后在QFutureWatcher发送finished时执行另一个函数,如下:

auto CallAsyncWithCallback = [](auto func_async, auto func_callback){
		auto future = QtConcurrent::run(globalThreadPool(), func_async);
		auto watcher = new QFutureWatcher<void>();
		// 连接信号,此处connect会被自动执行为Qt::QueuedConnection
		QObject::connect(watcher, &QFutureWatcher<void>::finished, [func_callback, watcher]() mutable { 
				func_callback();
				watcher->deleteLater(); // 完成后自动清理
			});
		watcher->setFuture(future);
	}

上面的connect是在调用线程中执行的,而finished信号是在线程池中子线程中发出来的,跨线程所以Qt会选择用Qt::QueuedConnection的方式执行Lambda 表达式。

方案四,有时,我们希望回调函数在特定线程比如主线程中执行,如下:

auto CallAsyncWithUICallback = [](FuncAsync func_async, FuncCallback func_callback_onUI) {
		QtConcurrent::run([func_async, func_callback]() {			
			func_async(); // 在子线程执行异步函数
			
			// 回到主线程执行回调
			QMetaObject::invokeMethod(qApp, [func_callback]() {
				func_callback();
				}, Qt::QueuedConnection);
			});
	}

注意,在调用invokeMethod时,要显示指定Qt::QueuedConnection。

总体来说,C#的async await很灵活很强大,Qt虽然不能与之相比,但经过简单的封装,也能写出比较灵活或者符合自己业务需求而又简洁好读的异步代码。

到此这篇关于Qt使用QtConcurrent::run实现异步等待和同步调用的文章就介绍到这了,更多相关Qt QtConcurrent::run异步等待和同步调用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • Qt timerEvent实现简单秒表功能

    Qt timerEvent实现简单秒表功能

    这篇文章主要为大家详细介绍了Qt timerEvent实现简单秒表功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • C++与C语言的区别你知道吗

    C++与C语言的区别你知道吗

    这篇文章主要为大家详细介绍了C++与C的区别,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • c语言算术运算符越界问题解决方案

    c语言算术运算符越界问题解决方案

    大量的安全漏洞是由于计算机算术运算的微妙细节引起的, 具体的C语言, 诸如符号数和无符号数之间转换, 算术运算的越界都会导致不可预知的错误和安全漏洞, 具体的案例数不胜数.
    2012-11-11
  • C语言全方位讲解指针的使用

    C语言全方位讲解指针的使用

    指针是C语言中一个非常重要的概念,也是C语言的特色之一。使用指针可以对复杂数据进行处理,能对计算机的内存分配进行控制,在函数调用中使用指针还可以返回多个值
    2022-04-04
  • C++实现五子棋游戏

    C++实现五子棋游戏

    这篇文章主要为大家详细介绍了C++实现五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • C++实现马踏棋盘(骑士周游)

    C++实现马踏棋盘(骑士周游)

    这篇文章主要为大家详细介绍了C++实现马踏棋盘,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • C语言数据在内存中的存储流程深入分析

    C语言数据在内存中的存储流程深入分析

    使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。您可能需要存储各种数据类型的信息,操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么
    2022-10-10
  • C语言求向量和的两则问题解答分享

    C语言求向量和的两则问题解答分享

    这篇文章主要介绍了C语言求向量和的两则问题解答分享,分别是求连续子向量的最大和和任何连续最接近0的子向量的和的问题,需要的朋友可以参考下
    2016-04-04
  • C语言打印输出杨辉三角

    C语言打印输出杨辉三角

    这篇文章主要为大家详细介绍了C语言打印输出杨辉三角,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • C语言的运算符你了解吗

    C语言的运算符你了解吗

    这篇文章主要介绍了C语言中的运算符,本文给大家介绍的非常详细,具有参考借鉴价值,需要的朋友可以参考下,希望能给你带来帮助
    2021-08-08

最新评论