=================================版权声明=================================

版权声明:原创文章 禁止转载 

请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我

勿用于学术性引用。

勿用于商业出版、商业印刷、商业引用以及其他商业用途。                   

 

本文不定期修正完善。

本文链接:https://www.cnblogs.com/wlsandwho/p/13837290.html

耻辱墙:http://www.cnblogs.com/wlsandwho/p/4206472.html

=======================================================================

C++ 异步

=======================================================================

如果可能,创建一个线程执行DoSomething(1),

根据被执行函数的实际耗时,res=f.get()+res2会有不同行为,

但最终都会执行。

注意:

1 async支持显式的发射策略,虽然指明async策略可以不用再调用get,但是为了统一和更明确,调一下也无妨,万一根据代码量评估绩效呢。

2 一个future对象的get方法只能被调用一次,之后的调用是无效的。(用valid方法检测)

但是wait方法可以调用多次。(但是不返回结果,需要再调用get。)

3 wait_for和wait_until不会让defferred的任务启动

4 wait和get一定会让任务启动并完成。

  1 // AsyncAndFuture.cpp : 定义控制台应用程序的入口点。
  2 //
  3 #include "stdafx.h"
  4 #include <windows.h>
  5 
  6 #include <iostream>
  7 #include <future>
  8 
  9 //////////////////////////////////////////////////////////////////////////
 10 int DoSomething(int n)
 11 {
 12     //模拟功能的函数
 13     Sleep(n * 1000);
 14 
 15     return n;
 16 }
 17 
 18 int DoSomethingWithMagic(int n)
 19 {
 20     //模拟功能的函数
 21     Sleep(n * 999);
 22 
 23     return n;
 24 }
 25 
 26 int DoSomethingWithShow(int n)
 27 {
 28     //模拟功能的函数
 29     std::cout << "Do\n";
 30     Sleep(n * 1000);
 31     std::cout << "Done\n";
 32 
 33     return n;
 34 }
 35 
 36 int DoSomethingByVal(int i,const std::shared_future<int>& sf)
 37 {
 38     int val = sf.get();
 39 
 40     return i + val;
 41 }
 42 
 43 //////////////////////////////////////////////////////////////////////////
 44 void Test1()
 45 {
 46     //基本用法
 47 
 48     std::future<int> f = std::async(DoSomething, 1);
 49 
 50     int res2 = DoSomething(2);
 51 
 52     int res = f.get() + res2;
 53 
 54     std::cout << res << std::endl;
 55 }
 56 
 57 //////////////////////////////////////////////////////////////////////////
 58 void Test2()
 59 {
 60     //发射策略
 61 
 62     //std::future<int> f = std::async(std::launch::async,DoSomething,1);
 63     //std::future<int> f = std::async(std::launch::deferred,DoSomething,1);
 64 }
 65 
 66 //////////////////////////////////////////////////////////////////////////
 67 void Test3()
 68 {
 69     //缓式求值
 70 
 71     auto f1 = std::async(std::launch::deferred, DoSomething, 1);
 72     auto f2 = std::async(std::launch::deferred, DoSomething, 2);
 73 
 74     bool bWhich = true;
 75     auto res = bWhich ? f1.get() : f2.get();
 76     std::cout << res << std::endl;
 77 }
 78 
 79 //////////////////////////////////////////////////////////////////////////
 80 void Test4()
 81 {
 82     //wait可调用多次,get只能调用一次
 83 
 84     auto f1 = std::async(std::launch::deferred, DoSomething, 1);
 85     f1.wait();
 86     //f1.wait();//多次调用,没问题
 87     auto res=f1.get();
 88 
 89     std::cout << res << std::endl;
 90 
 91     //auto res2 = f1.get();//多次调用,此处异常
 92 }
 93 
 94 //////////////////////////////////////////////////////////////////////////
 95 void Test5()
 96 {
 97     //虽然同一个future对象的get只能调用一次,
 98     //但是给future对象赋值后,又有了新的对象,又是一条好汉,可以调用(看汇编是用的forward实现的=重载)
 99 
100     int res = 0;
101 
102     std::future<int> f = std::async(DoSomething, 1);
103     res = f.get();
104     std::cout << res << std::endl;
105 
106     f = std::async(DoSomething, 2);
107     res = f.get();
108     std::cout << res << std::endl;
109 }
110 
111 //////////////////////////////////////////////////////////////////////////
112 class CBestRest
113 {
114 public:
115     std::future<int> f;
116 };
117 
118 CBestRest oBR;
119 
120 void Test6()
121 {
122     //投机性运行,选取有限时间内最好的结果
123 
124     int res = 0;
125 
126     //尝试用一种方法得到精确解
127     auto deadline = std::chrono::system_clock::now() + std::chrono::seconds(3);
128     oBR.f = std::async(DoSomethingWithMagic, 5);
129 
130     //规规矩矩的解,不是很精确
131     int resguess = DoSomething(2);
132 
133     //时间到了,算出精确解就用,万一精确解没算完,我们就用普通的解
134     std::future_status fs = oBR.f.wait_until(deadline);
135     if (fs==std::future_status::ready)
136     {
137         res = oBR.f.get();
138     }
139     else
140     {
141         res = resguess;
142     }
143 
144     std::cout << res << std::endl;
145 }
146 
147 //////////////////////////////////////////////////////////////////////////
148 void Test7()
149 {
150     //使用shared_future,多次调用get
151 
152     std::shared_future<int> sf = std::async(std::launch::async, DoSomething, 5);
153 
154     auto f1 = std::async(DoSomethingByVal, 1, sf);
155     auto f2 = std::async(DoSomethingByVal, 2, sf);
156     auto f3 = std::async(DoSomethingByVal, 3, sf);
157 
158     //这三行是顺序的,这里是在等结果,因为它们的耗时以最大的那个为准,所以还是可以看作并行的。
159     int res1 = f1.get();
160     int res2 = f2.get();
161     int res3 = f3.get();
162 
163     std::cout    << res1 << std::endl
164                 << res2 << std::endl
165                 << res3 << std::endl;
166 }
167 
168 //////////////////////////////////////////////////////////////////////////
169 void Test8()
170 {
171     //wait_for不会启动任务(wait_until同理)
172     std::future<int> f = std::async(std::launch::deferred,DoSomethingWithShow, 2);
173     std::future_status fs = f.wait_for(std::chrono::seconds(1));
174 
175     if (fs==std::future_status::deferred)
176     {
177         std::cout << "Did not Run for deferred\n";
178     }
179 
180     getchar();
181 
182     //任务超时的例子
183     std::future<int> f2 = std::async(std::launch::async, DoSomethingWithShow, 2);
184     std::future_status fs2 = f2.wait_for(std::chrono::seconds(1));
185 
186     if (fs2 == std::future_status::timeout)
187     {
188         std::cout << "Run but timeout\n";
189     }
190 }
191 
192 
193 int main()
194 {
195     Test1();
196     Test2();
197     Test3();
198     Test4();
199     Test5();
200     Test6();
201     Test7();
202     Test8();
203 
204     getchar();
205 
206     return 0;
207 }

 

运行结果(Test8输入了一个a并回车以便让程序继续运行)