您的位置:首页 > 大数据 > 人工智能

async/task/await

2017-11-08 10:45 429 查看
async/task/await三组合是.NET Framework 4.5带给.NET开发者的大礼,合理地使用它,可以提高应用程序的吞吐能力。

但是它的使用有点绕人,如果不正确使用,会带来意想不到的问题——比如await之后一直在等待,等到花儿也谢了,也等不来。

这篇博文将向你展示我们在实际开发中遇到的这个问题。

先看一段ASP.NET MVC示例代码:

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

private string GetResponseHtml(string url)
{
return GetResponseContentAsync(url).Result;
}

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";
}
}
}


代码说明:

在上面的代码中,虽然在Action方法之前加了async Task<ActionResult>,但由于在方法体中没有使用await,所以实际还是以同步的方式执行的,与直接使用ActionResult是一样的。

GetResponseHtml是同步方法,GetResponseContentAsync是异步方法,在GetResponseHtml中调用了异步的GetResponseContentAsync。(如果调用的是第三方程序集,我们就不知道在GetResponseHtml中进行了异步调用,所以这个方法的设计是有问题的)

这段代码执行结果会是怎样呢?

——结果就是没有结果,一直在执行。。。

(注:如果在控制台应用程序中调用同样的GetResponseHtml,不会出现这个问题)

那如果解决这个问题呢:

解决方法一:在MVC Action中开启一个Task进行await

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


解决方法二:将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);
}


显然,第2个解决方法是更好的。

所以,我们在设计一个方法(method)时,如果调用了async方法,一定要将这个方法本身设计为async的。不然,别人调用时很容易踩着这个坑,然后就一直等啊等。。。等到花儿谢了,电脑冒烟了,也等不到。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: