我有以下测试代码。循环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();
以下是复制问题的步骤。
在VS 2012中创建一个控制台项目。
请将我的代码复制并粘贴到Main中。
将断点放在此行“log.ErrorException(string.Format(”SoeHtike) {0}”, Task.CurrentId) 离);“
以调试模式运行程序。等几分钟。 (可能是5分钟?)我刚刚测试了我的代码,3分钟后我就得到了例外。如果你有fiddler,你可以监视请求,以便你知道程序是否仍在运行。
如果你不能复制这个问题,请随时告诉我。
答案 0 :(得分:63)
默认HttpClient.Timeout
值为100秒(00:01:40)。如果您在catch
块中执行时间戳,您会发现任务在此时开始被取消。显然,每秒可以执行的HTTP请求数量有限,其他请求排队。排队请求在超时时被取消。在所有600k的任务中,我个人只获得了2500次成功,其他任务被取消了。
我也觉得不太可能,你将能够运行整个60万个任务。许多网络驱动程序仅在很短的时间内通过大量请求,并在一段时间后将该数量减少到非常低的值。我的网卡允许我在36秒内仅发送921个请求,并将该速度降低到每秒只有一个请求。在这个速度下,完成所有任务需要一周的时间。
如果您能够绕过该限制,请确保为64位平台构建代码,因为应用程序非常渴望内存。
答案 1 :(得分:34)
不要处置您正在使用的HttpClient实例。很奇怪,但我找到了这个问题。
答案 2 :(得分:1)
只是想分享 我有一个类似的代码来加载测试我们的服务器,并且你的请求超时的概率很高。 您可以将http请求的超时设置为max,并查看它是否为您更改了任何内容。 我尝试通过创建各种线程来访问我们的服务器。并且它增加了命中率,但它们最终都会超时。而且当你在另一个线程上击中它们时,你也无法设置超时。
答案 3 :(得分:0)
我最近遇到了这个问题。事实证明,当我以调试模式启动Web应用程序时,启动URL使用的是https。
但是,WebApi端点的URL(在我的配置文件中)使用的是http。将其更新为使用https后,便可以调用WebApi端点。