有效使用ASP.NET Web API的async / await

我想在我的Web API项目中使用ASP.NET的async/await功能。 我不太确定它是否会对我的Web API服务的性能产生影响。 请在下面找到我的应用程序中的工作流程和示例代码。

工作流程:

UI应用程序→Web API端点(控制器)→Web API服务层中的调用方法→调用另一个外部Web服务。 (这里我们有数据库交互等)

控制器:

public async Task<IHttpActionResult> GetCountries()
{
    var allCountrys = await CountryDataService.ReturnAllCountries();

    if (allCountrys.Success)
    {
        return Ok(allCountrys.Domain);
    }

    return InternalServerError();
}

服务层:

public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
    var response = _service.Process<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");

    return Task.FromResult(response);
}

我测试了上述代码并正在工作。 但我不确定是否正确使用async/await 。 请分享你的想法。


我不太确定它是否会对API的性能产生影响。

请记住,服务器端异步代码的主要优点是可伸缩性。 它不会神奇地让你的请求运行得更快。 我在我的关于async ASP.NET的文章中介绍了几个“我应该使用async ”的注意事项。

我认为你的用例(调用其他API)非常适合异步代码,只要记住“异步”并不意味着“更快”。 最好的方法是首先让你的UI响应和异步; 这会让您的应用程序感觉速度更快,即使速度稍慢。

就代码而言,这不是异步的:

public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
  var response = _service.Process<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
  return Task.FromResult(response);
}

你需要一个真正的异步执行获得的可扩展性优势async

public async Task<BackOfficeResponse<List<Country>>> ReturnAllCountriesAsync()
{
  return await _service.ProcessAsync<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
}

或者(如果你在这个方法中的逻辑真的只是一个传递):

public Task<BackOfficeResponse<List<Country>>> ReturnAllCountriesAsync()
{
  return _service.ProcessAsync<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
}

请注意,从“内向外”而不是像“外在”这样的工作更容易。 换言之,不要从异步控制器操作开始,然后强制下游方法异步。 相反,请确定自然异步操作(调用外部API,数据库查询等),并使这些异步处于最低级别( Service.ProcessAsync )。 然后让async流淌,使您的控制器操作异步作为最后一步。

并且在任何情况下都不应该在这种情况下使用Task.Run


这是正确的,但也许没有用。

由于没有什么可以等待的 - 没有阻止可异步操作的API的调用 - 那么您将设置结构来跟踪异步操作(其开销),但不会使用该功能。

例如,如果服务层正在使用支持异步调用的实体框架执行数据库操作:

public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
    using (db = myDBContext.Get()) {
      var list = await db.Countries.Where(condition).ToListAsync();

       return list;
    }
}

你可以让工作线程在查询数据库时做其他事情(从而能够处理另一个请求)。

等待时间往往是需要一直下降的事情:很难对现有系统进行改造。


您没有有效地利用异步/等待,因为执行同步方法时请求线程会被阻塞ReturnAllCountries()

分配用于处理请求的线程将空闲等待,而ReturnAllCountries()它是有效的。

如果您可以实现ReturnAllCountries()以异步,那么您会看到可扩展性的好处。 这是因为线程可能被释放回.NET线程池来处理另一个请求,而ReturnAllCountries()正在执行。 通过更有效地利用线程,这将使您的服务具有更高的吞吐量。

链接地址: http://www.djcxy.com/p/54329.html

上一篇: Effectively use async/await with ASP.NET Web API

下一篇: WCF Data Services (OData) Vs ASP.NET Web API