C# 异步代码导致阻塞
在 UI界面或者ASP.NET中调用async的异步代码时如果async和task.Result混用会出现线程被阻塞锁死的情况。
导致阻塞的示例代码:
public static async Task<JObject> GetJsonAsync(Uri uri) { // 请勿在实际使用过程中将 httpclient 放在 using 中,此处仅是示例 using (var client = new HttpClient()) { var jsonString = await client.GetStringAsync(uri); return JObject.Parse(jsonString); } } public void Button1_Click(...) { var jsonTask = GetJsonAsync(...); textBox1.Text = jsonTask.Result; }
阻止死锁的两种办法:
使用 ConfigureAwait(false)
public static async Task<JObject> GetJsonAsync(Uri uri) { using (var client = new HttpClient()) { var jsonString = await client.GetStringAsync(uri).ConfigureAwait(false); return JObject.Parse(jsonString); } }
默认情况下,当您使用async/await时,它将在开始请求的原始线程上继续运行(状态机)。但是,如果当前另一个长时间运行的进程已经接管了该线程,那么你就不得不等待它完成。要避免这个问题,可以使用ConfigureAwait的方法和false参数。当你用这个方法的时候,这将告诉Task它可以在任何可用的线程上恢复自己继续运行,而不是等待最初创建它的线程。这将加快响应速度并避免许多死锁。
但是,当使用此方法后,线程同步上下文将丢失,从而转变成异步操作,如果在之后继续操作界面元素等,会提示线程不安全。
使用 Async 方法进行调用
public async void Button1_Click(...) { var json = await GetJsonAsync(...); textBox1.Text = json; }
原文链接地址:http://blog.exsvc.cn/article/csharp-async-deadlock.html
转载请注明:转载自 易科博客 ,谢谢!