首页 > 后端开发 > C++ > 为什么在ASP.NET中使用`等待'/`async`时有时会僵局``httpclient.getAsync(...)?

为什么在ASP.NET中使用`等待'/`async`时有时会僵局``httpclient.getAsync(...)?

Mary-Kate Olsen
发布: 2025-01-25 13:37:09
原创
549 人浏览过

Why does `HttpClient.GetAsync(...)` sometimes deadlock when using `await`/`async` in ASP.NET?

ASP.NET 中 HttpClient.GetAsync(...) 使用 await/async 时偶尔死锁

在 .NET 4.5 中使用新的 async/await 语言功能和 Tasks API 时,httpClient.GetAsync(...) 的 "awaiting" 结果有时可能会卡住。这是由于 API 的误用造成的。

解释

在 ASP.NET 中,一次只有一个线程能够处理一个请求。如果需要,可以执行并行处理,但是需要从线程池中借用额外的线程,这些线程没有请求上下文。这由 ASP.NET SynchronizationContext 管理。

默认情况下,当等待一个 Task 时,方法会在捕获的 SynchronizationContext 或捕获的 TaskScheduler 上恢复(如果没有 SynchronizationContext)。通常情况下,这是理想的:异步控制器操作将等待某些内容,当它恢复时,它会使用请求上下文恢复。

Test5Controller.Get

此特定的控制器方法执行 AsyncAwait_GetSomeDataAsync(在 ASP.NET 请求上下文中)。AsyncAwait_GetSomeDataAsync 执行 HttpClient.GetAsync(在 ASP.NET 请求上下文中)。HTTP 请求被发送出去,HttpClient.GetAsync 返回一个未完成的 Task。然后,AsyncAwait_GetSomeDataAsync 等待未完成的 Task,因此它返回一个未完成的 Task。现在,Test5Controller.Get 阻塞当前线程,直到该 Task 完成。

HTTP 响应到来,HttpClient.GetAsync 返回的 Task 完成。然后,AsyncAwait_GetSomeDataAsync 尝试在 ASP.NET 请求上下文中恢复。但是,该上下文中已经有了一个线程:在 Test5Controller.Get 中阻塞的线程。这会导致死锁。

最佳实践

为了纠正这个问题,建议:

  • 尽可能在您的 "库" 异步方法中使用 ConfigureAwait(false)。在这种情况下,AsyncAwait_GetSomeDataAsync 将更改为 result = await httpClient.GetAsync("http://stackoverflow.com", HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
  • 避免阻塞 Tasks;使用 await 代替 "GetResult"(Task.ResultTask.Wait 也应该替换为 await)。

通过遵循这些最佳实践,延续(AsyncAwait_GetSomeDataAsync 方法的其余部分)将在没有必要进入 ASP.NET 请求上下文的普通线程池线程上运行,并且控制器本身是异步的(不会阻塞请求线程)。

以上是为什么在ASP.NET中使用`等待'/`async`时有时会僵局``httpclient.getAsync(...)?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板