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

Posted

技术标签:

【中文标题】HttpClient - 任务被取消 - 如何获得确切的错误消息?【英文标题】:HttpClient - task was cancelled - How to get the exact error message? 【发布时间】:2013-10-07 21:04:10 【问题描述】:

我有以下测试代码。循环 316934 或 361992 次后,我总是收到“任务已取消”错误。

如果我没记错的话,取消任务有两个可能的原因:a) HttpClient 超时或 b) 队列中的任务太多,某些任务超时。

我找不到有关排队任务限制的文档。我尝试创建超过 500K 的任务并且没有超时。我猜“b”的原因可能不正确。

第一季度。我错过了还有其他原因吗?

第二季度。如果是因为 HttpClient 超时,我怎样才能得到确切的异常消息而不是“TaskCancellation”异常。

第三季度。修复它的最佳方法是什么?我应该介绍节流器吗?

谢谢!

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();

这是复制问题的步骤。

    在 VS 2012 中创建控制台项目。

    请将我的代码复制并粘贴到 Main。

    把断点放在这一行" log.ErrorException(string.Format("SoeHtike 0", 任务.CurrentId), ex);"

在调试模式下运行程序。等待几分钟。 (也许 5 分钟?)我刚刚测试了我的代码,3 分钟后我得到了异常。如果您有提琴手,您可以监视请求,以便您知道程序是否仍在运行。

如果您无法复制该问题,请随时告诉我。

【问题讨论】:

你正在做的是让页面 600.000 它实际上是 DOS 攻击,你不应该这样做。 嗨,我明白了。但是有些网站可以处理巨大的请求。而且我真的很想知道为什么我得到“任务被取消”而没有实际的错误消息。 另外,我认为这不是阻止我请求的网站 @Pedro.The.Kid 也许他是在蛮横地强迫自己的网站建立针对 DOS 攻击的保护? 【参考方案1】:

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

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

如果您能够绕过该限制,请确保为 64 位平台构建代码,因为该应用非常需要内存。

【讨论】:

嗨,您能否详细说明您的答案。我遇到了同样的问题。我怎样才能知道我的应用中有多少任务正在运行? 超时。谢谢,这就是我想要的。【参考方案2】:

只是想分享 我有一个类似的代码来负载测试我们的服务器,并且您的请求很可能超时。 您可以将您的 http 请求的超时设置为最大,看看它是否对您有任何改变。 我尝试通过创建各种线程来访问我们的服务器。而且它增加了命中,但它们最终都会超时。而且你不能在另一个线程上命中它们时设置超时。

【讨论】:

【参考方案3】:

不要释放您正在使用的 HttpClient 实例。奇怪但为我解决了这个问题。

【讨论】:

我只是创建了一个控制台应用程序来向 API 发送大量请求以模拟“真实”世界案例,这是唯一对我有用的东西。肯定很奇怪。 哇,我一直在发疯,而且……你是唯一能解决这个问题的东西。和@jpgrassi 做的差不多。 这并不奇怪,MSDN 解释了为什么以及如何使用HttpClient。如果你有兴趣,你也可以检查类的 CIL,看看为什么不应该经常为自己处理。 @Sergey.quixoticaxis.Ivanov:本文的代码示例说(原文如此):“// HttpClient 对象使用完毕后需要调用 dispose,因此应用程序不会泄漏资源”。还有一个普遍和广泛接受的模式是处理所有实现 IDisposable 的东西。 @abatishchev HttpClient is intended to be instantiated once and re-used throughout the life of an application. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors 您的选择,但遵循这种被广泛接受的模式通常会使代码变慢、丑陋甚至不可靠(一般来说,当遇到像 HttpClient 这样 100% 不应该的类时那样使用)。【参考方案4】:

我最近遇到了这个。事实证明,当我在调试模式下启动 Web 应用程序时,启动 URL 使用的是 https。

但是,WebApi 端点的 URL(在我的配置文件中)使用的是 http。一旦我将它更新为使用 https,我就能够调用 WebApi 端点。

【讨论】:

以上是关于HttpClient - 任务被取消 - 如何获得确切的错误消息?的主要内容,如果未能解决你的问题,请参考以下文章

HttpClient - 任务被取消?

Web Api 的 PostAsync HttpClient 错误 - System.AggregateException“任务已取消。”

Flutter中如何取消任务

如何知道上下文是不是已被取消?

在 Task.WaitAll 中处理取消的任务和任务异常?

Xamarin HttpClient:TaskCancelledException