[英]Why do I have to use (async method).result instead of await (async method)?
[英]Why use async when I have to use await?
我一直坚持这个问题,并没有真正找到任何有用的澄清,为什么会这样。
如果我有一个async
方法,如:
public async Task<bool> MyMethod()
{
// Some logic
return true;
}
public async void MyMethod2()
{
var status = MyMethod(); // Visual studio green lines this and recommends using await
}
如果我await
这里使用await
,那么异步方法有什么意义呢? 难道它不会让VS告诉我await
的async
无用吗? 这不会破坏将任务卸载到线程而不等待它完成的目的吗?
如果我在这里使用await,那么异步方法有什么意义呢?
await
不会阻止线程。 MyMethod2
将同步运行,直到达到await
表达式。 然后MyMethod2
将被暂停,直到等待任务( MyMethod
)完成。 当MyMethod
未完成时,控件将返回MyMethod2
调用者。 这就是await
的一点 - 来电者将继续这样做 。
难道它不会让VS告诉我等待的异步无用吗?
async
只是一个标志,意思是'在方法的某个地方你有一个或多个等待'。
这不会破坏将任务卸载到线程而不等待它完成的目的吗?
如上所述,您不必等待任务完成。 这里什么都没有阻止。
注意:要遵循框架命名标准,我建议您将Async
后缀添加到异步方法名称。
这不会破坏将任务卸载到线程而不等待它完成的目的吗?
当然是。 但这不是await / async的目的 。 目的是允许您编写使用异步操作而不浪费线程的同步代码,或者更一般地说,允许调用者对或多或少的异步操作进行控制。
基本思想是,只要你正确使用await和async,整个操作就会显得同步。 这通常是件好事,因为你做的大多数事情都是同步的 - 比如说,你不想在请求用户名之前创建用户。 所以你会做这样的事情:
var name = await GetNameAsync();
var user = await RemoteService.CreateUserAsync(name);
这两个操作相互同步; 第二个不会(并且不能!)在第一个之前发生。 但它们(不一定)与其来电者同步。 一个典型的例子是Windows窗体应用程序。 想象一下,你有一个按钮,点击处理程序包含上面的代码 - 所有代码都在UI线程上运行,但同时,当你await
,UI线程可以自由地执行其他任务(类似于使用Application.DoEvents
直到操作完成)。
同步代码更易于编写和理解,因此这使您可以获得异步操作的大部分好处,而无需使代码更难理解。 并且你不会失去异步做事的能力,因为Task
本身只是一个承诺,你并不总是必须马上await
它。 想象一下GetNameAsync
需要花费很多时间,但与此同时,在完成之前你需要做一些CPU工作:
var nameTask = GetNameAsync();
for (int i = 0; i < 100; i++) Thread.Sleep(100); // Important busy-work!
var name = await nameTask;
var user = await RemoteService.CreateUserAsync(name);
现在你的代码仍然是美妙的同步 - await
是同步点 - 而你可以与异步操作并行做其他事情。 另一个典型示例是并行触发多个异步请求,但保持代码与所有请求的完成同步:
var tasks = urls.Select(i => httpClient.GetAsync(i)).ToArray();
await Task.WhenAll(tasks);
这些任务是相互异步的,但不是他们的调用者,这仍然是美妙的同步。
我已经制作了一个(不完整的) 网络样本 ,它以这种方式使用await。 基本的想法是,虽然大多数代码在逻辑上是同步的(有一个协议要遵循 - 请求登录 - >验证登录 - >读取循环......;你甚至可以看到并行等待多个任务的部分) ,当你实际有CPU工作时,你只使用一个线程。 Await使得这几乎是微不足道的 - 使用continuation或旧的Begin / End异步模型做同样的事情将会更加痛苦,特别是在错误处理方面。 Await让它看起来很干净。
异步方法不会在其他线程上自动执行。 实际上,情况恰恰相反: async
方法总是在调用线程中执行。 async
意味着这是一个可以产生异步操作的方法。 这意味着它可以在等待其他执行完成时将控制权返回给调用者。 因此, asnync
方法是一种等待其他异步操作的方法。
由于你在MyMethod2
无所事事, async
在这里没有任何意义,所以你的编译器会警告你。
有趣的是,实现async
方法的团队已经承认标记方法async
并不是必需的,因为只需在方法体中使用await
就可以让编译器将其识别为异步。 添加了使用async
关键字的要求,以避免对使用await
作为变量名的现有代码进行更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.