问题描述
场景:
- DotNet Core 3.1:它在900个请求后完全冻结,并开始引发System.Net.WebException。
- DotNet Framework 4.7.2:运行得很好。
- 我还尝试列出任务列表并将每个任务添加到
Parallel.ForEach
中,然后在Task.WhenAll(tasks)
之后等待所有任务完成(Parallel.ForEach
),结果相同。 - 我还尝试使用HttpWebRequest发出请求,并读取响应而不是使用WebClient,结果也相同。
这是DotNet Core 3.1的问题,还是我做错了什么?
这是我在两种情况下都运行的代码。
static void Main(string[] args)
{
if (!Directory.Exists(@"C:\temp\parallel_requests"))
Directory.CreateDirectory(@"C:\temp\parallel_requests");
// List with the request urls (simulated,in real life these urls will be the ones that we need)
var urls = new List<string>();
for (var i = 0; i < 2000; i++)
{
urls.Add(@"https://jsonplaceholder.typicode.com/todos/1");
}
// Get the requests in parallel
var random = new Random();
Parallel.ForEach(urls,new ParallelOptions { MaxDegreeOfParallelism = 3 },url =>
{
try
{
var client = new WebClient();
var jsonString = client.DownloadString(url);
File.WriteallText($@"C:\temp\parallel_requests\response_{DateTime.Now:yyyy.MM.dd_HH-mm-ss.fff}_{random.Next(10000,99999)}.ok.json",$"{url}\n{jsonString}");
}
catch (Exception err)
{
File.WriteallText($@"C:\temp\parallel_requests\response_{DateTime.Now:yyyy.MM.dd_HH-mm-ss.fff}_{random.Next(10000,99999)}.err.txt",$"{url}\n{err.Message}");
}
});
Debugger.Break();
}
这是2个屏幕快照,其中有两种情况的简短摘要。
解决方法
感谢@NikitaChayka的提示。
使用全局HttpClient并将Parallel.ForEach更改为AsParallel()。ForAll()解决了该问题。
static void Main(string[] args)
{
if (!Directory.Exists(@"C:\temp\parallel_requests"))
Directory.CreateDirectory(@"C:\temp\parallel_requests");
// List with the request urls (simulated,in real life these urls will be the ones that we need)
var urls = new List<string>();
for (var i = 0; i < 4000; i++)
{
urls.Add(@"https://jsonplaceholder.typicode.com/todos/1");
}
// Get the requests in parallel
var client = new HttpClient();
urls.AsParallel().ForAll(url =>
{
try
{
var response = client.GetAsync(url).Result;
response.EnsureSuccessStatusCode();
var jsonString = response.Content.ReadAsStringAsync().Result;
File.WriteAllText($@"C:\temp\parallel_requests\response_{DateTime.Now:yyyy.MM.dd_HH-mm-ss.fff}_{Guid.NewGuid()}.ok.json",$"{url}\n{jsonString}");
}
catch (Exception err)
{
File.WriteAllText($@"C:\temp\parallel_requests\response_{DateTime.Now:yyyy.MM.dd_HH-mm-ss.fff}_{Guid.NewGuid()}.err.txt",$"{url}\n{err.Message}");
}
});
Debugger.Break();
}