【问题标题】:Nested async & await in Web API applicationWeb API 应用程序中的嵌套异步和等待
【发布时间】:2021-08-03 08:51:32
【问题描述】:

我想使用 .NET Core 构建异步 Web API

如果我有 async Task 正在等待来自服务的结果,如下所示

        [HttpGet("User/")]
        public async Task<IActionResult> GetUser()
        {
            var result = await _service.GetUser();
            return Ok(result);
        }

现在在_service.GetUser 中,我们执行不止一项任务,例如多次查询数据库。

所以我的问题是我们是否必须在 _service.GetUser 中也使用 async 和 await,或者调用者方法是否足够?我有点困惑。

    public async Task<UserResponseDTO> GetUser(UserRequestDTO userRequestDTO)
    {
        var userId =  await _utilities.getUserId(); //shall we use it?
        var user = await _dbContext.getFullUserInfo //shall we use it?
           .Where(P => P.userId == userId).FirstOrDefault();
   

        if (!string.IsNullOrEmpty(userRequestDTO.email))
        {
            var emailExists = await _dbContext.getFullUserInfo.Where(p => 
             p.Email == userRequestDTO.email).AnyAsync();  //shall we use it?
        }
    
        await _dbContext.SaveChangesAsync();
        return _mapper.Map<UserResponseDTO>(user);
    }

【问题讨论】:

  • 您应该从所调用方法的顶部到底部一直执行 async/await,因此将 GetUser 设为 async 并等待其中的 async 调用是正确的。虽然我不认为你需要SaveChangesAsync,因为看起来你实际上并没有改变任何东西。
  • 您将如何不使用 使用await 来实现该方法?显然它是可能的(异步编程是在await 甚至被添加到语言之前完成的)但await 是专门添加的,因为它比替代方案容易得多。如果您只是删除了 await 关键字并且没有做任何其他事情,那么整个事情当然不会编译,所以您需要做 something
  • 想象一下,在例程中使用await 的需要取决于例程的调用者。你怎么知道如果你的调用者正在使用它?即使您确实知道这一点, 立即等待任务并将其存储以供稍后等待都是有效的技术,您如何区分它们?
  • @juharr 感谢您的回复。实际上 SaveChangesAsync() 是需要的,但为了简单起见,我不得不删除一些代码
  • @Servy 我在 GetUser 中等待一次调用 db。然后,随着我对 db 的调用增加,我觉得每个人都重复等待有些奇怪

标签: c# asp.net-core asynchronous async-await


【解决方案1】:

我想使用 .NET Core 构建异步 Web API

为什么?

这个问题有很多不正确的答案;最常见的可能是“使其更快”。 “为了使其更具可扩展性”我会说只是半正确的。

正确的答案是“我有异步工作要做”,这里的“异步”与“I/O-bound”大致相同。

在您的示例代码中,您需要一个异步 Web API 调用因为调用查询/更新数据库。

所以我的问题是我们是否必须在 _service.GetUser 中也使用 async 和 await 或者调用者方法是否足够?

一旦你对“为什么”有了正确的推理,解决方案就会更加清晰。具体来说,您希望首先拥有异步数据库方法,然后在调用它们时使您的 API 方法异步。

一般来说,最好从最低级别的调用开始,并让它们使用awaitFirstOrDefaultAsyncAnyAsyncSaveChangesAsync 等。任何做 I/O 的东西都可以改成使用await。一旦GetUser 是一个异步方法(应该称为GetUserAsync),然后让您的GetUser 操作方法使用async/await

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2018-06-04
    • 1970-01-01
    • 2018-06-25
    • 2020-10-17
    • 2012-07-31
    相关资源
    最近更新 更多