C++异步编程

关键词

std::async、std::paclaged_task、std::promise、std::future

知识点

#include <QCoreApplication>
#include <thread>
#include <mutex>
#include <future>
#include <QDebug>
#include <QThread>
#include <tuple>
/**关于std::future的说明:
**    future-期值,用来存储并发编程中的结果,也可以当做传参。
**常用的方法有:std::future::get(), 
**std::future与std::shared_future,前者的get方法仅有一次有效,一次后无效而std::shared_future可以多次get()
**除了std::future::get()和`std::future::wait()会阻塞线程,std::future的临时对象在调用`析构函数`时同样会阻塞当前线程。
**注意在局部区域内的`std::future`的析构。
*/

//测试STL中的并发编程
int FunAsync(){
    qDebug()<<"async!"<<QThread::currentThread();
    return 1;
}
int FunPackaged_task(){
    qDebug()<<"packaged_task!"<<QThread::currentThread();
    return 2;
}
void FunPromise(std::promise<std::tuple<int,double,uchar>>&& cd_){
    qDebug()<<"promise of 1!"<<QThread::currentThread();
    cd_.set_value(std::tuple<int,double,uchar>{1,2,3});
}
void FunPromise2(std::future<int>&& _future){
    qDebug()<<"promise of 2!"<<QThread::currentThread();
    qDebug()<<_future.get();
}


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    //!async
    std::future<int> future_async =//async会立即运行,运行结果存在返回的future中,std::launch::async用于强制开启多线程
    std::async(std::launch::async,std::move(FunAsync));  //返回结果存储在future中
    qDebug()<<future_async.get();  //结果可以用std::future::get得到

    //!packaged_task,本身不具有跨线程能力,需配合thread使用
    std::packaged_task<int()> pack_task(std::move(FunPackaged_task));
    std::future<int> packaged_task_result = pack_task.get_future();  //定义在那里获取结果,这步需要再运行前定义运行却是异步
    std::thread thread_packaged_task(std::move(pack_task));  //std::thread线程创建后就会立即执行
    qDebug()<<packaged_task_result.get();
    thread_packaged_task.join();  //std::thread请确保是join还是detach的结束方式,这是必须的!

    //!promise  #1,函数接收promise类型的传参,好处:直接执行并返回结果
    std::promise<std::tuple<int,double,uchar>> primise_data;  //用于线程穿梭的promise变量
    std::future<std::tuple<int,double,uchar>> primise_future = primise_data.get_future();  //定义结果返回于那个期值
    std::thread thread_promise(FunPromise,std::move(primise_data));  //线程直接执行
    std::tuple<int,double,uchar> promise_tem_res = primise_future.get();  //promise::get获取期值数据
    qDebug()<<"a:"<<std::get<0>(promise_tem_res)<<"b:"<<std::get<1>(promise_tem_res)<<"c:"<<std::get<2>(promise_tem_res);
    thread_promise.join();  //...

    //!#2,函数接收future,在主线程中调用,promise::set_value时才会在子线程中处理结果
    std::promise<int> future_promise_of_2;
    std::thread thread_promise2(FunPromise2,future_promise_of_2.get_future());
    future_promise_of_2.set_value(200);
    thread_promise2.join();

    return a.exec();
}

补充说明

//std::async
//a).当调用`std::future::get()`会阻塞当前线程,直到得到结果。
//b).当调用`std::async(fun*)`时,未必会在新的线程中执行,若明确要在新线程中执行,可以使用`std::launch::async`参数如:`
//    std::async(std::launch::async, func*)`;强制在新线程中执行。
//定义函数`
auto fun = [](int value) {
	std::this_thread::sleep_for(std::chrono::seconds(5)); //睡眠5s后返回结果`
	return 100 + value;
};
//创建仿函数(包装函数)
std::packaged_task<int(int)> pk_task{fun};
//定义仿函数返回值返回于何处
std::future<int> f = pk_task.get_future();

//配合线程正式调用,使用move来实现右值引用,后面跟``着需要的传参`
std::thread  t1(std::move(pk_task), 20);

1、packaged_task 可以认为是 仿函数,调用方式有两种:

//1、显式调用(直接调用),如上定义了`pk_task`伪函数,则可以:`pk_task(10)`进行直接调用,而后使用`std::future::get()`得到期值。
//2).异步调用,如a)中一样,通过移动语句把`pk_task(10)`的控制权交给新线程,并开始执行,但别忘了,线程需要`join`或`detach`,否则系统异常终止。
//注意:执行`pk_task`等价于执行`fun(10)`

 

posted @   Labant  阅读(79)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示