首頁 > 後端開發 > 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
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板