创建异步任务、延迟任务。任务或操作可以独立于主线程运行,主线程无需等待任务完成便可执行其他的任务,当异步的任务完成的时候可以通过某种机制获取其结果(std::future)
1、异步任务--async 正常使用环境 future.get
1#include<iostream> 2#include<thread> 3#include<chrono> 4#include<future> 5 6int task(int number) { 7 // 抛出异常 或 返回正常结果 8 std::cout<<"异步任务执行"<<std::endl; 9 // throw std::exception("异常抛出"); 10 std::this_thread::sleep_for(std::chrono::seconds(2)); 11 return 100+number; 12} 13 14void test() 15{ 16 // 下面代码执行完成之后,异步任务就开始执行 async 参数1:任务类型(async异步任务 deferred延迟任务) 参数2:真正要执行的任务函数 参数3:传递给任务函数的参数 17 // 函数返回值 future类型 用于获取异步任务结果的对象 模版参数 < > 中填写任务函数的返回类型 18 std::future<int> fut = std::async(std::launch::async, task, 10); 19 std::cout<<"任务开始执行..."<<std::endl; 20 21 try 22 { 23 // 阻塞等待任务函数执行结束,并得到结果 24 int ret = fut.get(); 25 std::cout<<"ret = "<< ret <<std::endl; 26 } 27 catch (const std::exception& ex) 28 { 29 std::cout<<ex.what()<<std::endl; 30 } 31 32 std::cout<<"程序结束"<<std::endl; 33} 34 35int main() 36{ 37 test(); 38 return 0; 39}
2、没有返回值的任务场景 future.wait wait_for wait_until
wait函数会阻塞等待任务函数执行结束(正常结束、异常结束),并不关心返回值。注意:如果任务函数抛出异常,wait函数不会再抛出异常,而是保存到std:future对象的内部,当调用get函数时会抛出异常。
A B 两个异步任务分别执行将不同的内容写入不同的文件中,然后由主线程将两个文件的内容合并到第三个文件中
1#include<iostream> 2#include<thread> 3#include<chrono> 4#include<future> 5#include<fstream> 6 7using namespace std; 8 9void write_file(string filename, string content) 10{ 11 ofstream ofs(filename); 12 // 等待2s,表示耗时任务 13 this_thread::sleep_for(chrono::seconds(2)); 14 15 ofs << content <<endl; 16 ofs.close(); 17} 18 19void test() 20{ 21 // 下面代码执行完成之后,线程函数就开始执行 22 future<void> fut1 = async(launch::async, write_file, "demo1.txt", "hello world"); 23 future<void> fut2 = async(launch::async, write_file, "demo2.txt", "hello C++"); 24 cout << "任务执行开始..." << endl; 25 26 // 等待异步任务执行完毕 27 fut1.wait(); 28 fut2.wait(); 29 30 // 合并文件 31 ifstream ifs1("demo1.txt"); 32 ifstream ifs2("demo2.txt"); 33 ofstream ofs("demo.txt"); 34 35 // 可以直接操作一个流的对象 参数2 就是结束的流 36 copy(istreambuf_iterator<char>(ifs1), istreambuf_iterator<char>(), ostreambuf_iterator<char>(ofs)); 37 copy(istreambuf_iterator<char>(ifs2), istreambuf_iterator<char>(), ostreambuf_iterator<char>(ofs)); 38 39 ifs1.close(); 40 ifs2.close(); 41 ofs.close(); 42 43 cout<<"程序结束"<<endl; 44} 45 46int main() 47{ 48 test(); 49 return 0; 50}
3、非阻塞获取结果 wait_for wait_until 非阻塞的方式来获取异步的结果
wait_for 会在指定时间内等待任务状态的变化,如果任务没有结束,返回timeout,否则返回ready
wait_until则表示等到某个时间点,如果任务没有发生变化,则返回timeout,否则返回ready
1#include<iostream> 2#include<thread> 3#include<chrono> 4#include<future> 5#include<fstream> 6 7using namespace std; 8 9int calculate(int number) 10{ 11 int result = 0; 12 for(int i = 0; i < number; ++i) 13 { 14 this_thread::sleep_for(chrono::seconds(1)); 15 result += 10; 16 } 17 return result; 18} 19 20void test() 21{ 22 future<int> fut = async(launch::async, calculate, 5); 23 cout << "任务开始执行..." << endl; 24 25 while(ture) 26 { 27 future_status status = fut.wait_for(chrono::seconds(1)); 28 // future_status status = fur.wait_until(chrono::steady_clock().now + chrono::seconds(2)); 29 if(status == future_status::ready) 30 { 31 cout<<"子线程结果"<< fut.get() <<endl; 32 break; 33 } 34 if(status == future_status::timeout) 35 { 36 cout<<"子任务尚未执行完成,做一会其他的事情..."<<endl; 37 } 38 } 39} 40 41int main() 42{ 43 test(); 44 return 0; 45} 46
4、async的延时任务
将任务的执行推迟,知道确实需要时才开始执行。这种方式通常用于系统负载较高时,任务的结果又不立即需要的场景,帮助系统优化资源使用,提升整体性能。
1#include<iostream> 2#include<thread> 3#include<chrono> 4#include<future> 5#include<fstream> 6 7using namespace std; 8 9int task(int number) 10{ 11 cout << "延迟任务执行" <<endl; 12 this_thread::sleep_for(std::chrono::seconds(8)); 13 return 100+number; 14} 15 16void test01() 17{ 18 // 任务不会马上执行 19 future<int> fut = async(launch::deferred, task,10); 20 21 // 当调用 get、wait函数时,触发任务函数的执行 22 int ret = fut.get(); 23 cout<<"ret = "<<ret <<endl; 24 // fut.wait(); 25 26 this_thread::sleep_for(std::chrono::seconds(3)); 27} 28 29void test02() 30{ 31 future<int> fut = async(launch::deferred, task, 10); 32 bool is_start = false; 33 34 while(true) 35 { 36 // 当延迟任务尚未执行前,wait_for 函数不会阻塞,会立即返回 有timeout deferred ready状态 37 future_status status = fut.wait_for(chrono::seconds(1)); 38 // is_start 避免多开线程 39 if(status == future_status::deferred && !is_start) 40 { 41 cout<<"任务尚未开始执行..."<<endl; 42 // 新开一个线程去执行函数 43 thread([&fut]() {fut.wait();}).detach(); 44 is_start = true; 45 } 46 47 if(status == future_status::timeout) 48 { 49 cout<<"任务正在执行..."<<endl; 50 } 51 52 if(status == future_status::ready) 53 { 54 cout<<"任务执行完毕,执行结果是"<<fut.get()<<endl; 55 break; 56 } 57 } 58} 59 60int main() 61{ 62 test02(); 63 return 0; 64}
5、延时任务,独享和共享任务结果
future获取任务结果,它适合一次性获取结果。多次获取会导致一次。当任务需要在多个地方或者多次获取结果的时候,需要使用到shared_future代替future。
1#include<iostream> 2#include<thread> 3#include<chrono> 4#include<future> 5#include<fstream> 6 7using namespace std; 8 9// 可以在async的返回时直接写 shared_future 也可以用future的share获取一个shared_future 10 11void test() 12{ 13 future<int> fut = async(launch::deferred, [](){ 14 cout<<"延迟任务开始..."<<endl; 15 this_thread::sleep_for(chrono::seconds(2)); 16 return 100; 17 }); 18 // future 只能获取一次结果,重复获取会有异常 19 // shared_future 可以获取多次 20}
6、延时任务的案例
用户在查看某张照片,但是只有处理过的照片才能展示给用户看,我们可以
1、集中时间处理所有图片,这样会在一段时间大量占用系统的资源,会影响系统的性能
2、按需处理图片,用户请求那张就开那个线程处理,处理过的图像直接返回,剩余未处理的可以在系统空闲的时候进行处理
1#include<iostream> 2#include<thread> 3#include<chrono> 4#include<future> 5#include<fstream> 6#include<map> 7 8using namespace std; 9 10string data_analysis(string path) 11{ 12 this_thread::sleep_for(chrono::seconds(10)); 13 return path; 14} 15 16void test() 17{ 18 map<string,tuple<bool,shared_future<string>>> tasks; 19 20 // 添加延迟图像处理的任务 21 tasks.insert({"a.png",{false,async(launch::deferred,data_analysis,"a.png")}}); 22 tasks.insert({"b.png",{false,async(launch::deferred,data_analysis,"b.png")}}); 23 tasks.insert({"c.png",{false,async(launch::deferred,data_analysis,"c.png")}}); 24 25 // 用户查看图像 26 string name; 27 while(true) 28 { 29 cout<<"请输入查看的图像:"; 30 cin>>name; 31 if(name == "exit") 32 { 33 for(auto &task : tasks) 34 { 35 cout<<task.first<<" "<<boolalpha<<get<0>(task.second)<<endl; 36 } 37 cout<<"--------------"<<endl; 38 break; 39 } 40 41 //查看图片的状态 42 auto& picture = tasks[name]; 43 auto& is_ok = get<0>(picture); 44 auto& fut = get<1>(pitcture); 45 46 if(is_ok) 47 { 48 cout<<"您要查看的图像是"<<fut.get()<<endl; 49 continue; 50 } 51 52 future_status status = fut.wait_for(chrono::seconds(1)); 53 if(status == future_status::deferred) 54 { 55 cout<<"图像尚未处理,开始处理图像..."<<endl; 56 thread([&fut](){fut.wait();}).detach(); 57 } 58 59 if(status == future_status::timeout) 60 { 61 cout<<"图像正在处理中"<<endl; 62 } 63 if(status == future_status::ready) 64 { 65 is_ok = true; 66 cout<<"您要查看的图像是1"<<fut.get()<<endl; 67 } 68 cout<<"============="<<endl'; 69 } 70} 71 72int main() 73{ 74 test(); 75 return 0; 76} 77
《C++ async 异步学习》 是转载文章,点击查看原文。
