c# - 当我必须使用 await 时,为什么要使用 async?

标签 c# .net asynchronous async-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,异步方法有什么意义呢? VS 告诉我调用 await 不会使 async 无用吗?这不会破坏在不等待任务完成的情况下将任务卸载到线程的目的吗?

最佳答案

Does that not defeat the purpose of offloading a task to a thread without waiting for it to finish?

当然可以。但这不是 await/async 的目的。。目的是让您能够编写使用异步操作的同步代码,而不会浪费线程,或者更一般地说,让调用者能够控制或多或少的异步操作。

基本思路是,只要正确使用await和async,整个操作就会看起来是同步的。这通常是一件好事,因为您所做的大部分事情 都是同步的 - 比如说,您不想在请求用户名之前创建用户。所以你会做这样的事情:

var name = await GetNameAsync();
var user = await RemoteService.CreateUserAsync(name);

这两个操作是同步的;第二个不会(也不可能!)发生在第一个之前。但它们(不一定)与其调用者同步。一个典型的例子是 Windows 窗体应用程序。假设您有一个按钮,点击处理程序包含上面的代码 - 所有代码都在 UI 线程上运行,但与此同时,当您在 awaiting 时,UI 线程可以自由地执行执行其他任务(类似于使用 Application.DoEvents 直到操作完成)。

同步代码更易于编写和理解,因此您可以在不使代码更难理解的情况下获得异步操作的大部分好处。而且您不会失去异步执行操作的能力,因为 Task 本身只是一个 promise ,您不必总是 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);

任务之间是异步的,但它们的调用者仍然是同步的。

我做了一个(不完整的)networking sample以这种方式使用 await 。基本思想是,虽然大部分代码在逻辑上是同步的(有一个协议(protocol)要遵循——请求登录->验证登录->读取循环……;你甚至可以看到并行等待多个任务的部分) ,您只有在实际有 CPU 工作要做时才使用线程。 Await 使这几乎变得微不足道——用延续或旧的 Begin/End 异步模型做同样的事情会更加痛苦,尤其是在错误处理方面。 Await 让它看起来很干净。

关于c# - 当我必须使用 await 时,为什么要使用 async?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42624647/

相关文章:

c# - 连接池使用相同的错误连接字符串向两个线程返回相同的异常实例?

c# - 如何结合 TaskCompletionSource 和 CancellationTokenSource?

ios - 在 UITableView Swift 中滚动时重复图像

c# - 在 EF Core 中自动填充 Created 和 LastModified

c# - 在字符串上使用 Razor 引擎 - 而不是 View

c# - 如何从 .mov 视频文件头(QuickTime 文件格式)中读取比特率信息?

c# - Visual Studio 2013 错误列表未显示失败构建的错误

java - 自动生成Word文档

c# - 路径中的哈希字符抛出 DirectoryNotFoundException

c# - 需要用异步数据库请求返回SqlDataReader