gpt4 book ai didi

c# - Web Api 中的异步调用

转载 作者:行者123 更新时间:2023-11-30 19:57:15 25 4
gpt4 key购买 nike

在 asp.net Web API 中,如何异步调用长时间运行的阻塞操作?

我有一个 Web API Controller 操作,需要进行相对(例如 10 秒)长时间运行的数据库调用。这似乎是异步方法的候选者。我可以将长时间运行的任务卸载到一个新线程上,并取消阻止我的 asp.net 请求线程来处理一些其他请求,因此我的简化 Controller 操作将如下所示:

public async Task<IHttpActionResult> Get()
{
IEnumerable<Thing> things = await Task.Run(() => DoLongDbCall());
return Ok(things);
}

我遇到过一些博客(例如 this one),它们表明这可能不是在 asp.net 中实现此目的的最佳方式。作者建议使用 Task.FromResult() 并同步进行数据库调用,但我看不出这有什么帮助;我的请求线程仍将被阻塞,等待数据库调用返回。

最佳答案

首先,考虑同步调用会发生什么:

public IHttpActionResult Get()
{
IEnumerable<Thing> things = DoLongDbCall();
return Ok(things);
}

一个请求进来,ASP.NET抢一个线程池线程来处理这个请求。该线程调用完成工作的 Get 方法。整个请求期间使用一个线程池线程。

现在,让我们来看看当前代码中发生了什么(使用 Task.Run):

public async Task<IHttpActionResult> Get()
{
IEnumerable<Thing> things = await Task.Run(() => DoLongDbCall());
return Ok(things);
}

一个请求进来,ASP.NET抢一个线程池线程来处理这个请求。此线程调用 Get 方法,然后获取 另一个 线程池线程来完成工作并将原始线程池线程返回给该线程水池。整个请求期间使用一个线程池线程(并且在很短的时间内使用两个线程池线程)。

因此,Task.Run 代码强制进行额外的线程转换,但没有提供任何好处(在服务器端使用 async 的全部意义在于释放线程) .这就是为什么我建议不要在 ASP.NET 上使用 Task.Run(或任何其他在线程池上运行工作的方式)。

一个合适的异步解决方案是使用异步数据库调用:

public async Task<IHttpActionResult> Get()
{
IEnumerable<Thing> things = await DoLongDbCallAsync();
return Ok(things);
}

一个请求进来,ASP.NET抢一个线程池线程来处理这个请求。该线程调用Get方法,然后启动异步操作,将线程池线程返回线程池。稍后,当 db 调用完成时,ASP.NET 会获取一个线程池线程来完成请求。对于大多数请求,使用线程池线程(一个线程池线程在请求​​的开始和结束时使用一小段时间)。

关于c# - Web Api 中的异步调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30864247/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com