【发布时间】:2021-02-04 06:35:39
【问题描述】:
我知道 asp.net 控制器类中的这个动作方法只使用几个线程就可以处理数千个并发请求,即使_httpClient.GetAsync 需要很多秒才能返回。这是因为HttpClient.GetAsync()(在 Windows 中)使用 I/O 完成端口,并且在GetAsync() 返回之前没有线程正在运行。
[HttpGet]
public async Task<object> GetData()
{
var result = await _httpClient.GetAsync("https://stackoverflow.com");
return result.StatusCode;
}
但是我们可以对异步数据库操作说同样的话吗? EF Core 是否使用了一些无线程异步,或者会为每个 await SaveChangesAsync() 调用创建一个新线程?
[HttpPost]
public async Task<ActionResult<object>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return ok;
}
当数据库在某个远程机器上时,它会利用一些套接字 IOCP,以便我们可以在更短的时间间隔内使用线程(仅适用于 db 中的非网络操作)?
如果在数据库操作的整个过程中都使用了一个新线程,那么我看不到任何 可扩展性 改进,因为对于每个请求,我都会完成启动 Controler/Action 的线程,而我只是开始一个新的(DB)。
在 Winforms 或 WPF 中,我们有一个可用性改进,因为 UI 需要保持响应,但在 Asp.Net Core 中没有 SynchronizationContext 或 UI 需要担心。
我看到 async/await 在 asp.net 核心中的更多地方使用(即 razor await Component.InvokeAsync),但它真的有用吗?
【问题讨论】:
-
我想如果你想更多地了解具体的
SaveChangesAsync,只要看看它的源代码。很难说它在幕后做了什么。async并不总是产生一个新线程,它取决于底层的任务调度程序。通常默认的 TaskScheduler 应该尽最大努力尽可能最有效地使用系统资源。很多开发人员并不真正需要关心它。最后,在尝试改进任何东西之前,您应该首先对所有内容进行基准测试以了解其性能是否足够。 -
HttpClient == 网络 (TCP)。数据库调用 == 网络(通常是 TCP)。你填补分歧?当然,这取决于 ADO.NET 提供程序的实现,但通常在 Windows 上,它们使用标准 TCP 类来建立连接。所以 IOCP 在这两种情况下都适用。
标签: c# asp.net-core async-await entity-framework-core