Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# HttpClient异步请求失败_C#_.net Core_Task Parallel Library_Dotnet Httpclient - Fatal编程技术网

C# HttpClient异步请求失败

C# HttpClient异步请求失败,c#,.net-core,task-parallel-library,dotnet-httpclient,C#,.net Core,Task Parallel Library,Dotnet Httpclient,我需要从大约3000个URL获取内容。我正在使用HttpClient,为每个url创建Task,将任务添加到列表中,然后等待任务。像这样的 var tasks = new List<Task<string>>(); foreach (var url in urls) { var task = Task.Run(() => httpClient.GetStringAsync(url)); tasks.Add(task);

我需要从大约3000个URL获取内容。我正在使用
HttpClient
,为每个url创建
Task
,将任务添加到列表中,然后
等待任务。像这样的

    var tasks = new List<Task<string>>();
    foreach (var url in urls) {
        var task = Task.Run(() => httpClient.GetStringAsync(url));
        tasks.Add(task);
    }

    var t = Task.WhenAll(tasks);
同样,几百个任务总是以错误告终

那么,这里的问题是什么?为什么我不能用
异步
获取这些URL

我使用的是.NETCore,因此使用ServicePointManager()的建议不适用


此外,我需要获取的URL指向不同的主机。httpbin的代码只是一个测试,以表明问题不在于我的URL无效。

正如Fildor在评论中所说,
httpClient.GetStringAsync
返回
任务
。因此,您不需要将其包装在
任务中。运行

我在控制台应用程序中运行了此代码。花了50秒才完成。在您的评论中,您写道curl在不到一分钟的时间内执行3000个查询-同样的事情

var httpClient = new HttpClient();
var tasks = new List<Task<string>>();
var sw = Stopwatch.StartNew();

for (int i = 0; i < 3000; i++)
{
    var task = httpClient.GetStringAsync("http://httpbin.org");
    tasks.Add(task);
}

Task.WaitAll(tasks.ToArray());
sw.Stop();

Console.WriteLine(sw.Elapsed);
Console.WriteLine(tasks.All(t => t.IsCompleted));
var-httpClient=new-httpClient();
var tasks=新列表();
var sw=Stopwatch.StartNew();
对于(int i=0;i<3000;i++)
{
var task=httpClient.GetStringAsync(“http://httpbin.org");
任务。添加(任务);
}
Task.WaitAll(tasks.ToArray());
sw.Stop();
控制台写入线(软件运行时间);
Console.WriteLine(tasks.All(t=>t.IsCompleted));
此外,所有请求都已成功完成


在代码中,您正在等待使用
Task.Run
启动的任务。但是,您需要等待通过调用
httpClient.Get…

启动的任务完成。为什么要将
httpClient.GetStringAsync(url)
包装到
Task.Run
?它已经为您提供了一个
任务
。此外,几乎同时启动所有这些请求,我实际上希望一些请求出现故障/超时。我会尝试使用
Parallel.ForEach
对并行性进行更多的控制。我猜
Task.WhenAll()
将在任何任务引发异常时失败。尝试在Try block中包装
httpClient.GetAsync()
。另请注意,一次用3000个请求轰炸一个url(或至少在很短的间隔内)可能会使您被洪水禁止或至少被限制。另外,用3000个请求轰炸httpbin.org,并发布邀请所有人都这样做的代码,可能会导致穷人的网站托管成本增加,并可能被视为一种温和的形式。所以我个人不打算尝试验证OP的实验。在“真实”场景中,3000个URL是否命中同一个主机?如果他们是(或者即使不是),那么在同一时间发起3000个请求是不可取的。一次考虑节流到50或100。您将发现使用Semphorsim和TPL数据流执行此操作的优秀示例。我不认为
任务。Run
是问题所在。此方法与异步委托一起使用时,将创建所创建的
任务的精简包装(代理)。在这种情况下,它没有任何好处,但也不应该有害(除了稍微损害代码的可读性之外)。
var httpClient = new HttpClient();
var tasks = new List<Task<string>>();
var sw = Stopwatch.StartNew();

for (int i = 0; i < 3000; i++)
{
    var task = httpClient.GetStringAsync("http://httpbin.org");
    tasks.Add(task);
}

Task.WaitAll(tasks.ToArray());
sw.Stop();

Console.WriteLine(sw.Elapsed);
Console.WriteLine(tasks.All(t => t.IsCompleted));