zoukankan      html  css  js  c++  java
  • 解决C#中一个"异步方法却同步执行"的问题

            几个月前做的一个软件里想添加一个天气预报功能, 也就是利用了一下Google Weather的接口: http://www.google.com/ig/api?hl=zh-cn&weather=某某市,某某省 , 效果也达到了.

            不忘书中所讲: 耗时操作, 且非计算密集型任务, 最好使用异步方法. 根据Anders Hejlsberg的视频中演示的那样, 我写出下面一段代码, 也是很多人拿来演示异步的经典写法:

            public void GetWeather(string city, string province)
            {
                var myRequest = (HttpWebRequest)WebRequest.Create("http://www.google.com/ig/api?hl=zh-cn&weather=" + city + "," + province);
                myRequest.BeginGetResponse(delegate(IAsyncResult ar)
                {
                var response = myRequest.EndGetResponse(ar);
                StreamReader weatherStream = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("gb2312"));
                string weatherString = weatherStream.ReadToEnd();
                weatherStream.Dispose();
                }, null);
            }

            就是这样的一个所谓异步的方法, 运行一下, 最短的时候花了3秒多才获取到了weatherString, 很多时候甚至花了10秒多. 我就眼巴巴的看着程序在假死(Not Responding), 一边看着我的代码, 我不是异步了么? 异步不是就是为了避免程序假死的么? 目前来看程序似乎并没有异步.

            于是开始找原因...也请教了不少人...也得到了一些可能的原因:

    • 嫌疑1: 程序运行的时候第一步在寻找DNS将google.com对应到某个具体的IP地址, 这项任务花费了不少时间.

            事实上我Ping了google.com之后, 把google.com换成IP地址, 运行程序, 并没有发现有什么效果...

    • 嫌疑2: 程序只实现了BeginGetResponse的异步, 还有GetResponseStream等等之类的方法并没有异步.

            但把GetResponseStream改成BeginGetResponseStream之后, 也没有任何改观.

    • 嫌疑3: 系统在给这个WebRequest分配资源, 诸如WebRequest类, StreamReader之类的还算"比较大"的对象花费了时间.

            想一想这些应该都是在高速缓存上进行的, 不至于要花3秒, 10多秒吧?

            这个问题还真不太好描述, 事实上后来做了一系列的测试, 测试发现只有第一次发出WebRequest看似不是异步的. 接下来继续尝试几次发出WebRequest, 到获得Response的时间就非常非常短. 为了找出究竟在哪个环节耗时比较厉害, 我写了一个控制台程序来测试, 测试中我用了一个for循环, 连续发出5次同样的WebRequest, 测试结果如下:

            可以发现程序在第一次初始化WebRequest和第一次从发出请求到获得响应消耗的时间最多! 昨天发现原来是代理(Proxy)的问题! MSDN中关于HttpWebRequest.Proxy属性是这样描述的:

    本地计算机或应用程序配置文件可能指定使用默认代理。 如果指定了 Proxy 属性,则 Proxy 属性中的代理设置会重写本地计算机或应用程序配置文件,并且 HttpWebRequest 实例将实用指定的代理设置。 如果配置文件中未指定代理并且未指定 Proxy 属性,则 HttpWebRequest 类使用从本地计算机上的 Internet Explorer 中继承的代理设置。 如果 Internet Explorer 中没有代理设置,请求会直接发送到服务器。

            回到遇到的问题, 程序并没有指定代理, 第一次运行的时候, 程序会寻找IE中的代理, 如果没有找到才会去直接访问服务器, 这中间花费了不少时间. 要解决这个问题, 请在代码中加上这么一行:

    xxRequest.Proxy = null;

    作者:Create Chen
    出处:http://technology.cnblogs.com
    说明:文章为作者平时里的思考和练习,可能有不当之处,请博客园的园友们多提宝贵意见。
    知识共享许可协议本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。

  • 相关阅读:
    DNNClassifier 深度神经网络 分类器
    浏览器对MP4视频 帧宽度 高度的兼容性
    UnicodeEncodeError:'latin-1' codec can't encode character
    文件夹下 文件计数
    the largest value you actually can transmit between the client and server is determined by the amount of available memory and the size of the communications buffers.
    the “identity” of an object
    广告特征 用户特征
    如果一个维度全覆盖,则有效维度应该对该维度全覆盖
    a high-level neural networks AP
    使用 LDA 挖掘的用户喜好主题
  • 原文地址:https://www.cnblogs.com/technology/p/2005351.html
Copyright © 2011-2022 走看看