我很困惑为什么我的parallels.for循环不断在httpclient调用上爆炸。 该代码适用于大约10-15个请求,然后将挂起很长时间并且出现System.AggregateException错误 我尝试了多种不同的变体,包括webclient。 请考虑以下事项:
class Program
{
static void Main(string[] args)
{
Parallel.For(0, 250, i =>
{
var task = GetPages.CallHttp();
task.Wait();
var content = task.Result;
TestObject obj = content.ToTestObject(); //take the string and find some values in it.
Console.WriteLine(obj.H1Tag);
});
}
}
public static class GetPages
{
private static readonly HttpClient client = new HttpClient() {Timeout = new TimeSpan(0,5,0)};
public static async Task<string> CallHttp()
{
client.DefaultRequestHeaders.UserAgent.ParseAdd("customAgent/1.0");
string astr = await client.GetStringAsync("the url I am testing").ConfigureAwait(false);
return astr;
}
}
public static class StringExtensions
{
private static readonly object objLock = new object();
public static TestObject ToTestObject(this string content)
{
lock (objLock)
{
var obj = new TestObject();
// creates a bunch of properties inspecting the html string
var result = new HtmlExtractions(content);
obj.PageTitle = result.PageTitle;
obj.H1Tag = result.H1Tag;
...
return obj;
}
}
}
public class HtmlExtractions
{
internal HtmlDocument doc;
public HtmlExtractions(string contentToRead)
{
doc = new HtmlDocument();
doc.LoadHtml(contentToRead);
}
public string PageTitle => doc.DocumentNode.Descendants("title").FirstOrDefault()?.InnerHtml.Replace("&", "&").Trim();
...
}
结果是抛出以下异常。
System.AggregateException was unhandled by user code
HResult=-2146233088
Message=One or more errors occurred.
Source=mscorlib
StackTrace:
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at ConsoleApplication1.Program.<>c.<Main>b__0_0(Int32 i) in c:\users\username\documents\visual studio 2015\Projects\ConsoleApplication1\Program.cs:line 27
at System.Threading.Tasks.Parallel.<>c__DisplayClass17_0`1.<ForWorker>b__1()
InnerException:
HResult=-2146233029
Message=A task was canceled.
InnerException: Id = 50, Status = Canceled, Method = "{null}", Result = "{Not yet computed}"
******根据Todd的建议更新//代码中的评论。太令人沮丧了。即使扩展到5个请求也会导致挂起。 ******
static async void RunPagesAsync()
{
Console.WriteLine("getting contents");
var tasks = Enumerable.Range(0, 5).Select(i => GetPages.CallHttp());
var contents = await Task.WhenAll(tasks);
Console.WriteLine("Got Contents..continuing");
foreach (var content in contents)
{
TestObject obj = content.ToTestObject(); //take the string and find some values in it.
Console.WriteLine(obj.H1Tag);
}
Console.WriteLine("completed");
}
static void Main(string[] args)
{
//Task.Run(() => RunPagesAsync()); //doesn't work.
// RunPagesAsync(); //just hangs after what looks like 2 itterations
// var tasks = Enumerable.Range(0, 5).Select(i => GetPages.CallHttp());
// var contents = await Task.WhenAll(tasks); //won't compile under synch Main dues to await
// foreach (var content in contents)
// {
// TestObject obj = content.ToTestObject(); //take the string and find some values in it.
// Console.WriteLine(obj.H1Tag);
// }
var tasks1 = Enumerable.Range(0, 5).Select(i => GetPages.CallHttp());
var contents1 = Task.WhenAll(tasks1);
contents1.Wait();
foreach (var content in contents1.Result)
{
TestObject obj = content.ToTestObject(); //take the string and find some values in it.
Console.WriteLine(obj.H1Tag);
}
答案 0 :(得分:1)
异步任务(免费线程)和Parallel.For
(强制使用多线程)不会很好地混合。当与异步任务一起使用时,.Wait()
和.Result
都会阻止调用并邀请死锁。尝试使用Main
重新编写Task.WhenAll
方法并避免阻止调用:
var tasks = Enumerable.Range(0, 250).Select(i => GetPages.CallHttp());
var contents = await Task.WhenAll(tasks);
foreach (var content in contents)
{
TestObject obj = content.ToTestObject(); //take the string and find some values in it.
Console.WriteLine(obj.H1Tag);
}