防止async / await 阻塞死鎖
阿新 • • 發佈:2020-09-08
介紹
async/await中使用阻塞式程式碼會導致死鎖
下面這段程式碼會導致死鎖,程式卡死
private void btnTest_Click(object sender, EventArgs e) { var htmlTask = GetHtmlAsync(new Uri("https://www.taobao.com")); MessageBox.Show(htmlTask.Result); } public static async Task<string> GetHtmlAsync(Uri uri) { using (var client = new HttpClient()) { var html = await client.GetStringAsync(uri); return html; } }
防止死鎖
- 在你的非同步方法中,返回未完成Task時都呼叫ConfigureAwait(false)。
- 始終使用 Async,不要混合阻塞式程式碼和非同步程式碼(推薦)。因為當你在非同步程式碼中阻塞程式,將失去非同步程式碼帶來的所有好處。
ConfigureAwait:
ConfigureAwait(continueOnCapturedContext: false):continueOnCapturedContext引數表示是否嘗試將延續任務封送回原始上下文。
ConfigureAwait(false)改變了GetJsonAsync的延續行為,使它不用在原來的context中恢復。GetJsonAsync將直接線上程池執行緒中恢復,這使得GetJsonAsync能完成任務,並且無需重新進入原來的context
private void btnTest_Click(object sender, EventArgs e) { var htmlTask = GetHtmlAsync(new Uri("https://www.taobao.com")); MessageBox.Show(htmlTask.Result); } public static async Task<string> GetHtmlAsync(Uri uri) { using (var client = new HttpClient()) { var html = await client.GetStringAsync(uri).ConfigureAwait(false); return html; } }
在ASP.NET Core框架中,已經移除SynchronizationContext。所以像上面案例中的用法不會出現死鎖,但是你不能保證你的非同步方法不被winform、wpf、asp.net使用