[C++]std::async异步操作 笔记

相关文档:http://zh.cppreference.com/w/cpp/thread/async

这只是一篇个人学习笔记,如有错误欢迎指出

咕了C++一段时间,我又回来学习了,这次是关于STL里自带的线程相关的模板函数`async` 。

async可以非常方便地用来创建一个异步任务,不同于基于libuv那种事件轮回型的异步编程,这个异步是使用一个新的线程来执行任务,而coder不用自己去管理新的线程。

根据参考文档的介绍:

模板函数 async 异步地运行函数 f (潜在地在可能是线程池一部分的分离线程中),并返回最终将保有该函数调用结果的 std::future 。

那么通过这个函数创建的异步任务可能是通过一个自动管理的线程池提供的线程来执行的,所以使用这个方法就不用太关心线程创建和销毁的开销(但也不要滥用)。

调用async会返回一个`std::future` 类,它定义于头文件 <future> (std::async也在这里面)。`future`是用来获取异步任务执行结果的类。

要注意的是,如果宿主进程尝试使用`get` 方法获取异步任务结果时任务还没有执行完,那么宿主会被阻塞,直到异步结果可以获取到。所以你用它的时候得自己设计个逻辑防止主进程被卡住。

接下来上例子,这个代码是从最顶上给的参考链接里的演示改来的

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <future>

using std::future_status;//使用future里的future_status
 
typedef std::vector<int> intvec;//定义一个存放int的vector类型

void newtask(){//一个求和任务
	intvec v(400000000, 1);//创建一个包含400000000个1的vector
	system("read -p \"按enter开启任务\"");
	std::cout<<"主:开始新任务"<<'\n';
	auto handle = std::async(std::launch::async,[&](intvec itr)->int{
		std::cout<<"次:计算中"<<'\n';
		return std::accumulate(itr.begin(), itr.end(), 0);//求和
	},v);

	std::cout<<"主:另一个进程正在计算"<<'\n';
	switch(handle.wait_for(std::chrono::seconds(2))){//等待两秒
		case future_status::deferred:{
			std::cout<<"主:计算仍未启动"<<'\n';
			break;
		}
		case future_status::ready:{
			std::cout<<"主:计算完成"<<'\n';
			std::cout<<"主:结果为 "<< handle.get() << '\n';
			break;
		}
		case future_status::timeout	:{
			std::cout<<"主:计算超时"<<'\n';
			break;
		}
	}
}

int main(){
	newtask();
}

async的第一个参数是一个枚举,有两个值可选:

  • std::launch::async :(在新的线程里)异步执行这个任务,就是上面说了很多的异步任务。
  • std::launch::deferred :(在当前线程里)惰性执行这个任务。这个模式存在的意义是什么我还不知道,没见着实际应用场景,也没给例子。具体行为是等到进程去get这个future的结果时再去执行这个任务,文档称之为惰性求值。

第二个参数是我们要丢进去当做异步任务入口的函数,在这里我写了个内联函数,如果不知道是啥的话可以看我上一篇笔记

从第三个参数开始是可变数量参数包,它们会在新线程被传递给前面这个任务函数,在这里我只写了一个参数。

 

接下来用future类的wait_for方法给异步任务加一个2秒超时,然后任务完成或者超时后,流程会到达下面的某一个分支。若任务还没完成的话,此方法也会阻塞宿主进程。

最后用get方法获取异步任务的结果,也就完成了整个async的使用流程。



本文发布于 https://luojia.me

本站文章未经文下加注授权不得拷贝发布。

0 0 投票数
打分
订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论