标签:
最近在深入研究异步模式和async, await关键字的时候看到了Stephen Cleary的这篇文章感觉又提高了一下对这两个keyword的了解,原文链接如下
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
考虑下面的示例。单击按钮将启动其他呼叫和显示在文本框中 (此示例是为 Windows 窗体,但同样的原则适用于任何 UI 应用程序) 的结果
// My "library" method. public static async Task<JObject> GetJsonAsync(Uri uri) { using (var client = new HttpClient()) { var jsonString = await client.GetStringAsync(uri); return JObject.Parse(jsonString); } } // My "top-level" method. public void Button1_Click(...) { var jsonTask = GetJsonAsync(...); textBox1.Text = jsonTask.Result; }
和上面非常相似的例子,执行 REST 调用库方法,只是这次它 ASP.NET 上下文中使用 (示例是Web API ,但适用于任何 ASP.NET 应用程序)
// My "library" method. public static async Task<JObject> GetJsonAsync(Uri uri) { using (var client = new HttpClient()) { var jsonString = await client.GetStringAsync(uri); return JObject.Parse(jsonString); } } // My "top-level" method. public class MyController : ApiController { public string Get() { var jsonTask = GetJsonAsync(...); return jsonTask.Result.ToString(); } }
同样原因,这段代码也会造成死锁。
第一个要点:一个等待另一个任务完成的方法要继续执行时是在一个上下文中执行。在第一种情况下,这种情况下是一个 UI 上下文 (适用于任何 UI 除了控制台应用程序)。在第二种情况下,是 ASP.NET 请求上下文。
另一个要点 ︰ ASP.NET 请求上下文不依赖于特定的线程 (用户界面是),但它一次仅允许一个线程进入。
下面是会发生的事情,我们从顶层方法 (Button1_Click UI / MyController.Get 为 ASP.NET)开始说:
在UI 示例中,"上下文"是用户界面上下文; 在ASP.NET 示例中,"上下文"是 ASP.NET 请求上下文。
怎样避免死锁
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); } }
public async void Button1_Click(...) { var json = await GetJsonAsync(...); textBox1.Text = json; } public class MyController : ApiController { public async Task<string> Get() { var json = await GetJsonAsync(...); return json.ToString(); } }
标签:
原文地址:http://www.cnblogs.com/odyssey/p/5539228.html