当您等待异步调用时——这真的是 C# 中的异步编程吗

Ope*_*ack 3 c# multithreading asynchronous task-parallel-library async-await

我有三层 .net Web API 应用程序。每一层都实现一个异步方法。每个调用都是asyncand ,我们await在每个步骤中都使用。我的问题是,当您await执行每一步时,它不会使应用程序同步并达不到目的吗?async wait 真正提供了什么价值?它会自动使用多个CPU 核心吗?

控制器:

public async Task<IHttpActionResult> Get()
{
    return Ok(await _service.Create());
}
Run Code Online (Sandbox Code Playgroud)

中间层:

public async Task<MyObject> Create()
{
    return await _repository.CreateAsync(new MyDataObject());
}
Run Code Online (Sandbox Code Playgroud)

D B

public async Task<T> CreateAsync(T data)
{
    var o = _dbSet.Add(data);
    await _dbContext.SaveChangesAsync();
    return 100;
}
Run Code Online (Sandbox Code Playgroud)

Ed *_*bbs 5

在您的示例中,您肯定正在进行异步处理。你没有做的是并行处理。.NET 文档并不总是能很好地区分两者。我将在这里介绍异步。

async/背后的主要思想await(你的例子做得很好)是当线程可以做一些有用的事情时不要无所事事。

拿你的CreateAsync例子来说:

public async Task<T> CreateAsync(T data)
{
    var o = _dbSet.Add(data);
    await _dbContext.SaveChangesAsync();
    return 100;
}
Run Code Online (Sandbox Code Playgroud)

由于await. 那么有什么好处呢?为了便于论证,假设如下:

  • 您的应用有 5 个用户
  • 您的应用程序有 2 个可用线程(很低,但可以继续使用)
  • 每次数据库保存需要3秒

现在假设用户A和用户B同时保存一条记录。每个都有自己的线程(这是事实,而不是假设)。如果您不使用await,则用户 A 和 B 将保留两个可用线程 3 秒,等待保存完成。没有更多线程可用,因此用户 C、D 和 E 将在此期间被阻止。

当您使用 时await,线程会被释放,因为它们只是......等待。现在他们可以处理用户 C、D 和 E。保存完成后,线程将返回用户 A 和 B 并完成该CreateAsync方法。

最重要的是,当async/await正确完成时,n 个线程可以满足多于n 个请求。

这是一个简化的解释,但我真的希望当初能得到一个简单的解释。我希望这有帮助。

  • 发送数据库写入;数据库正在执行写入操作;阻塞 API 线程只是等待数据库响应是没有意义的。另请参阅[ASP.NET 上的异步简介](https://learn.microsoft.com/en-us/archive/msdn-magazine/2014/october/async-programming-introduction-to-async-await-on- asp-net)和[没有线程](https://blog.stephencleary.com/2013/11/there-is-no-thread.html),都是你真正的。 (3认同)
  • @StephenCleary 我希望几年前就看过你的文章。一想到异步花了多长时间我就脸红了。我读了大量的文章,但他们总是设法通过对并行处理的讨论来污染解释,或者直接深入细节,最好留到以后,让我彻底困惑。非常感谢这些链接。 (2认同)