• 等到花儿也谢了的await


    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的。不然,别人调用时很容易踩着这个坑,然后就一直等啊等。。。等到花儿谢了,电脑冒烟了,也等不到。

    【相关链接】

  • 相关阅读:
    mq概念
    Mac Xampp 安装redis 及 安装php-redis扩展
    rabbitmq死信队列(延迟队列)demo
    rabbitmq生产与消费测试
    RabbitMQ各方法详解
    Mac git old mode 100644 new mode 100755 mac目录权限问题
    mac安装redis
    msql创建用户并授权
    mac apache php 访问失败
    Kubernetes入门学习--在Ubuntu16.0.4安装配置Minikube
  • 原文地址:https://www.cnblogs.com/sjqq/p/7341027.html
Copyright © 2020-2023  润新知