1. 程式人生 > 實用技巧 >防止async / await 阻塞死鎖

防止async / await 阻塞死鎖

介紹

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使用

參考:
https://www.cnblogs.com/heyuquan/p/async-deadlock.html