防止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

原文地址:https://www.cnblogs.com/fanfan-90/p/13631162.html