多个等待.Net WebApi中的异步

ili*_*ian 6 c# async-await asp.net-web-api

我们有许多使用await/ async关键字的异步控制器和服务.

许多动作看起来有点像:

public async Task<SomeViewModel> Get(int id)
{
    var someData = await _service.GetData(id);
    var someOtherData = await _service.GetMoreData(id);
    return new SomeViewModel
    {
        Data = someData,
        OtherData = someOtherData,
    }
}
Run Code Online (Sandbox Code Playgroud)

可能是服务调用本身也有await多个问题.这await通常是针对async实体框架,服务总线或第三方Web端点的调用.

我的一位同事今天提出这样的代码是毫无意义的,它只会为线程管理生成额外的工作,而在负载下,我们实际上会为运行时生成更多的工作并将应用程序减慢为结果.

他们是正确的,如果那么什么被认为是最好的做法async/ await当你在Web API请求多个IO绑定调用?

Ste*_*ary 10

我的一位同事今天提出这样的代码是毫无意义的,它只会为线程管理生成额外的工作,而在负载下,我们实际上会为运行时生成更多的工作并将应用程序减慢为结果.

这很有趣,因为事实恰恰相反.正如其他回答者所指出的那样,如果你使用的是真正的异步操作(即,不是Task.Run或者类似的东西),那么使用线程就会减少,而且应用程序在负载下的响应会更好.

有些人(不是我)已经完成了对"平均"ASP.NET应用程序转换的研究async,他们发现在迁移async到阻塞调用时,可扩展性提高了10倍到100倍.如果您的应用程序有更多异步工作要做,您可以期望更好的可伸缩性.

如果你看一个单一的请求,如果各种操作在一段时间做了一个,然后异步版本是稍微慢一些.但是,如果您将系统视为一个整体 - 特别是在负载下 - 异步版本可以更好地扩展.经常被忽略的异步处理程序的另一个方面是异步版本对突发加载的响应比线程池本身更快.

此外,异步代码可以轻松执行并发请求,这也可以使个别请求更快:

public async Task<SomeViewModel> Get(int id)
{
  var someDataTask = _service.GetData(id);
  var someOtherDataTask = _service.GetMoreData(id);
  await Task.WhenAll(someDataTask, someOtherDataTask);
  return new SomeViewModel
  {
    Data = await someDataTask,
    OtherData = await someOtherDataTask,
  }
}
Run Code Online (Sandbox Code Playgroud)