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

18 浏览
0 Comments

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

我正在尝试在我的Web API项目中使用ASP.NET的async/await特性。我不太确定它是否会对我的Web API服务的性能产生任何影响。请看下面是我的应用程序的工作流程和示例代码。\n工作流程:\n用户界面应用程序→Web API端点(控制器)→调用Web API服务层中的方法→调用另一个外部Web服务(这里涉及数据库交互等)。\n控制器:\n

public async Task GetCountries()
{
    var allCountrys = await CountryDataService.ReturnAllCountries();
    if (allCountrys.Success)
    {
        return Ok(allCountrys.Domain);
    }
    return InternalServerError();
}

\n服务层:\n

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

\n我测试了上述代码,它有效。但我不确定是否正确使用了async/await。请分享您的想法。

0
0 Comments

在ASP.NET Web API中有效地使用async/await的原因是,当执行同步方法ReturnAllCountries()时,请求线程将被阻塞。

负责处理请求的线程将会空闲等待,而ReturnAllCountries()执行其工作。

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

这是不正确的。套接字已连接,但处理请求的线程可以做其他事情,例如处理不同的请求,同时等待服务调用。

0
0 Comments

原因:在ASP.NET Web API中使用async/await时,如果没有等待任何可以异步操作的阻塞API调用,那么设置异步操作的结构会带来额外的开销,但却没有充分利用异步操作的能力。

解决方法:如果服务层使用Entity Framework执行DB操作,可以使用异步调用来提高性能。在这种情况下,可以使用async/await来让工作线程在查询数据库时可以处理其他请求。但是,要注意,async/await需要在整个系统中都进行相应的修改,很难后期添加到现有系统中。

以下是一个示例代码:

public async Task>> ReturnAllCountries()
{
    using (db = myDBContext.Get()) {
        var list = await db.Countries.Where(condition).ToListAsync();
        return list;
    }
}

在这个示例中,使用async/await来异步查询数据库,从而允许工作线程在查询数据库时可以处理其他请求。

0
0 Comments

在ASP.NET Web API中,如何有效地使用async/await是一个常见的问题。下面的内容提供了这个问题出现的原因以及解决方法。

在服务器端,异步代码的主要好处是可扩展性。它不会神奇地使您的请求运行更快。我在我的文章中提到了几个“是否应该使用async”的考虑因素。

代码示例中的ReturnAllCountries方法不是异步的,为了获得async的可扩展性优势,需要进行真正的异步实现。

在处理这个问题的时候,从“内部到外部”比从“外部到内部”更容易。也就是说,不要从异步控制器操作开始,然后强制要求下游方法成为异步的。相反,首先确定自然异步的操作(调用外部API,数据库查询等),并首先在最低级别(Service.ProcessAsync)将这些操作异步化。然后让async逐步上升,最后一步将控制器操作设置为异步。

在这种情况下,绝对不应该使用Task.Run。

关于为什么不应该在这里使用Task.Run的问题,Stephen在他的文章中简要解释了。他在他的博客中更详细地解释了。

在ASP.NET请求到达并开始运行时,它在线程池线程上运行,这没问题。但是,如果它变为异步,它将启动异步处理,该线程将立即返回到线程池。但在异步方法中执行的工作本身将在线程池线程上执行。

异步I/O操作不会阻塞线程。

总结起来,要有效地使用async/await,需要将异步操作放在最低级别,并逐步向上引入async。不要使用Task.Run来实现异步操作。

0