[英]When to use the “await” keyword
I'm writing a web page, and it calls some web services. 我正在写一个网页,它会调用一些Web服务。 The calls looked like this: 这些电话看起来像这样:
var Data1 = await WebService1.Call();
var Data2 = await WebService2.Call();
var Data3 = await WebService3.Call();
During code review, somebody said that I should change it to: 在代码审查期间,有人说我应该将其更改为:
var Task1 = WebService1.Call();
var Task2 = WebService2.Call();
var Task3 = WebService3.Call();
var Data1 = await Task1;
var Data2 = await Task2;
var Data3 = await Task3;
Why? 为什么? What's the difference? 有什么不同?
Servy's answer is correct; Servy的回答是正确的; to expand on that a little. 稍微扩大一点。 What's the difference between: 有什么区别:
Eat(await cook.MakeSaladAsync());
Eat(await cook.MakeSoupAsync());
Eat(await cook.MakeSandwichAsync());
and 和
Task<Salad> t1 = cook.MakeSaladAsync();
Task<Soup> t2 = cook.MakeSoupAsync();
Task<Sandwich> t3 = cook.MakeSandwichAsync();
Eat(await t1);
Eat(await t2);
Eat(await t3);
? ?
The first is: 首先是:
Your second program is equivalent to: 你的第二个计划相当于:
You see the difference? 你看到了区别? In your original program you don't tell the cook to start the next course until you are done eating the first course. 在原来的计划,你不告诉厨师,开始下一疗程,直到你吃完第一道菜。 In your second program you request all three courses up front, and eat them -- in order -- as they come available. 在你的第二个课程中,你提前申请所有三个课程,并按顺序吃它们 - 因为它们可用。 The second program makes better use of the cook's time because the cook can "get ahead" of you. 第二个程序更好地利用了厨师的时间,因为厨师可以“领先”你。
In the first code snippet you're not even starting the second service call until the first service call completes (and likewise not starting the third until the second completes). 在第一个代码片段中,您甚至不会在第一个服务调用完成之前启动第二个服务调用(同样在第二个服务调用完成之前不会启动第三个服务调用)。 In short, they are executed sequentially. 简而言之,它们是按顺序执行的。
In the second snippet you start all three service calls, but then don't continue on in the code until all three are done. 在第二个片段中,您启动所有三个服务调用,但在代码完成之前不要继续执行。 In short, they are all executed in parallel. 简而言之,它们都是并行执行的。
If the second/third calls are unable to be started until they have the result of the previous operation then you would need to do something like the first snippet in order to make it work. 如果第二次/第三次调用无法启动,直到它们具有上一次操作的结果,那么您需要执行类似第一个代码段的操作才能使其正常工作。 If the service calls don't depend on each other at all then you'd want them to be executed in parallel for performance reasons. 如果服务调用完全不依赖于彼此,那么出于性能原因,您希望它们并行执行。
If, for some reason, you really dislike having the extra local variables, there are other ways of executing the tasks in parallel using alternate syntaxes. 如果由于某种原因,您真的不喜欢使用额外的局部变量,那么还有其他方法可以使用备用语法并行执行任务。 One alternative that would act like your second option is: 一种可能与您的第二种选择相似的替代方案是:
var Data = await Task.WhenAll(WebService1.Call(),
WebService2.Call(),
WebService3.Call());
Servy posted a very good answer, but here is a visual description using Task
s to help show what the problem is. Servy发布了一个非常好的答案,但这是一个使用Task
来帮助显示问题的视觉描述。 This code will not be functionaly the same as yours (it does not do all the synchronization context stuff like giving back control to the message pump) but it illustrates the problem very well. 这段代码与你的代码不同(它没有完成所有同步上下文的操作,例如将控制权交还给消息泵),但它很好地说明了这个问题。
Your code is doing something like this 你的代码正在做这样的事情
var fooTask = Task.Factory.StartNew(Foo);
fooTask.Wait();
var fooResult = fooTask.Result;
var barTask = Task.Factory.StartNew(Bar);
barTask.Wait();
var barResult = barTask.Result;
var bazTask = Task.Factory.StartNew(Baz);
bazTask.Wait();
var bazResult = bazTask.Result;
and the corrected code is doing something like this 并且纠正的代码正在做这样的事情
var fooTask = Task.Factory.StartNew(Foo);
var barTask = Task.Factory.StartNew(Bar);
var bazTask = Task.Factory.StartNew(Baz);
fooTask.Wait();
var fooResult = fooTask.Result;
barTask.Wait();
var barResult = barTask.Result;
bazTask.Wait();
var bazResult = bazTask.Result;
You can see that all 3 tasks are running while waiting for the first result to get back, where in the first example the 2nd task does not start until the first task is finished. 您可以看到所有3个任务在等待第一个结果返回时正在运行,在第一个示例中,第二个任务在第一个任务完成之前不会启动。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.