HttpClient - 任务被取消 - 如何获取确切的错误消息?

Mic*_*ync 51 c# httpclient async-await

我有以下测试代码.循环316934或361992次后,我总是得到"任务被取消"错误.

如果我没有错,那么任务被取消的原因有两个:a)HttpClient超时或b)队列中的任务太多而某些任务超时.

我找不到关于排队任务的限制的文档.我尝试创建超过500K的任务,没有超时.我猜"b"的原因可能不对.

Q1.我错过了还有其他原因吗?

Q2.如果是因为HttpClient超时,我怎么能得到确切的异常消息而不是"TaskCancellation"异常.

Q3.什么是解决它的最佳方法?我应该介绍一下节流器吗?

谢谢!

var _httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "text/html,application/xhtml+xml,application/xml");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Encoding", "gzip, deflate");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Charset", "ISO-8859-1");

int[] intArray = Enumerable.Range(0, 600000).ToArray();

var results = intArray                
    .Select(async t => {

        using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, "http://www.google.com")) {
            log.Info(t);

            try {

                var response = await _httpClient.SendAsync(requestMessage);
                var responseContent = await response.Content.ReadAsStringAsync();

                return responseContent;
            }
            catch (Exception ex) {
                log.ErrorException(string.Format("SoeHtike {0}", Task.CurrentId), ex);
            }
            return null;
        }
    });

Task.WaitAll(results.ToArray());

Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)

这是复制问题的步骤.

  1. 在VS 2012中创建一个控制台项目.

  2. 请将我的代码复制并粘贴到Main中.

  3. 将断点放在此行"log.ErrorException(string.Format("SoeHtike {0}",Task.CurrentId),ex);"

以调试模式运行程序.等几分钟.(可能是5分钟?)我刚刚测试了我的代码,3分钟后我就得到了例外.如果你有fiddler,你可以监视请求,以便你知道程序是否仍在运行.

如果你不能复制这个问题,请随时告诉我.

Dmi*_*mov 64

默认HttpClient.Timeout值为100秒(00:01:40).如果您在catch块中执行时间戳,您会注意到任务在此时开始被取消.显然,每秒可以执行的HTTP请求数量有限,其他请求排队.排队请求在超时时被取消.在所有600k的任务中,我个人只获得了2500次成功,其他任务被取消了.

我也发现不太可能,你将能够运行整个600000的任务.许多网络驱动程序仅在很短的时间内通过大量请求,并在一段时间后将该数量减少到非常低的值.我的网卡允许我在36秒内仅发送921个请求,并将该速度降低到每秒只有一个请求.以这个速度完成所有任务需要一周时间.

如果您能够绕过该限制,请确保为64位平台构建代码,因为应用程序非常渴望内存.


aba*_*hev 34

不要处置您正在使用的HttpClient实例.奇怪,但为我解决了这个问题.

  • @abatishchev`HttpClient旨在实例化一次,并在应用程序的整个生命周期中重复使用.为每个请求实例化一个HttpClient类将耗尽重负载下可用的套接字数量.这将导致SocketException错误`您的选择,但遵循这种广泛接受的模式通常会使代码变得缓慢,丑陋甚至不可靠(通常,当遇到类似`HttpClient`的类时,100%并不意味着以这种方式使用). (2认同)