由于GUI 应用程序 不能使用线程池的线程更新UI,只能使用 GUI 线程更新,所以在 await 前后需要保证是同一个 GUI 线程
ASP.NET 程序 的线程处理客户端请求的时候,需要假定客户端的语言文化和身份标识等,所以为了保证信息的统一性,await 前后 会用同一个线程来处理...
那么,在 FCL 的 SynchronizationContext 就使用这样的线程模型来解决以上问题。因此偶尔也会带来一些问题:如下,
protected void Page_Load(object sender, EventArgs e) { try { Task<string> t = GetPage(); //主线程等待异步方法结束 Response.Write(t.Result); } catch (Exception ex) { Response.Write(ex.Message); } } private async Task<string> GetPage() { WebRequest req = WebRequest.Create("http://www.baidu.com/"); //线程返回 WebResponse resp = await req.GetResponseAsync(); //等待执行,但是永远执行不到,因为 需要同一个主线程执行,但是主线程在等待该方法执行结束, 死锁!!! Stream stream = resp.GetResponseStream(); StreamReader reader = new StreamReader(stream); return reader.ReadToEnd(); }
由于很多应用程序不需要依赖特定的应用程序模型,所以避免使用SynchronizationContext 对象,所以用 ConfigureAwait() 方法解决死锁问题
1 protected void Page_Load(object sender, EventArgs e) 2 { 3 try 4 { 5 Task<string> t = GetPage(); 6 //主线程等待异步方法结束 7 Response.Write(t.Result); 8 } 9 catch (Exception ex) 10 { 11 Response.Write(ex.Message); 12 } 13 } 14 15 private async Task<string> GetPage() 16 { 17 WebRequest req = WebRequest.Create("http://www.baidu.com/"); 18 //ConfigureAwait(false) 不依赖 线程处理模型,可用线程池线程唤醒状态机 19 WebResponse resp = await req.GetResponseAsync().ConfigureAwait(false); 20 Stream stream = resp.GetResponseStream(); 21 StreamReader reader = new StreamReader(stream); 22 return reader.ReadToEnd(); 23 }