异步多线程 ASP.NET 同步调用异步 使用Result产生死锁

  一个方法调用了async方法,要将这个方法本身设计为async。

public class BlogController : Controller
{
public async Task<ActionResult> AwaitDemo()
{
      //虽然写了async,但是没有await,所以还是同步
var responseHtml = GetResponseHtml("http://www.cnblogs.com/");
return Content(responseHtml);
}
  
  //同步方法
private string GetResponseHtml(string url)
{
     //调用了异步方法,而且用Result获取返回值
return GetResponseContentAsync(url).Result;
}

  //异步方法 async/await
private async Task<string> GetResponseContentAsync(string url)
{
var httpClient = new System.Net.Http.HttpClient();
var response = await httpClient.GetAsync(url);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return await response.Content.ReadAsStringAsync();
}
else
{
return "error";
}
}
}

  运行程序,一致卡死,而在控制台应用程序中调用同样的GetResponseHtml,不会出现问题,因为控制台没有同步上下文SynchronizationContext

,而ASP.NET程序有同步上下文AspNetSynchronizationContext,异步执行完后,找到前边的AspNetSynchronizationContext。

  改造方法:

  1、开启Task,进行await

  GetResponseHtml方法还是同步,而AwaitDemo,变成了异步

public async Task<ActionResult> AwaitDemo()
{
var responseHtml = await Task.Factory.StartNew(() =>
GetResponseHtml("http://www.cnblogs.com/"));
return Content(responseHtml);
}

  2、将GetResponseHtml变成异步方法

  异步到底

public async Task<ActionResult> AwaitDemo()
{
var responseHtml = await GetResponseHtml("http://www.cnblogs.com/");
return Content(responseHtml);
} private async Task<string> GetResponseHtml(string url)
{
return await GetResponseContentAsync(url);
}
上一篇:commonJS,常用js工具方法


下一篇:sublinme 快捷键格式