我需要编写一个异步加载和解析多个网站的方法。 这是我的方法的简化代码。
using (HTMLParser parser = new HTMLParser(proxy))
{
var tasks = totalSites.Select( s =>
{
return new Task( async () =>
{
s.Entity = await parser.GetSiteDataAsync(s.Entity).ConfigureAwait(false);
});
}).ToArray();
foreach (var task in tasks)
task.Start();
await Task.WhenAll(tasks).ConfigureAwait(false);
}
HTMLParser
类使用HttpClient
加载网站并将其置于dispose上。完整代码还使用CancellationToken
取消,SemaphoreSlim
以降低并行度。
问题是当任务开始等待解析数据时,它的状态设置为RanToCompletion
。然后程序通过Task.WhenAll
并在HTMLParser
中处理导致OperationCanceledException
的{{1}}。
答案 0 :(得分:4)
就像我在评论中所说,你不应该明确地创建Task
。我认为你需要的是:
using (HTMLParser parser = new HTMLParser(proxy))
{
var tasks = totalSites.Select( s => populateEntity(s)).ToArray();
/* returned tasks are already hot */
//foreach (var task in tasks)
// task.Start();
await Task.WhenAll(tasks).ConfigureAwait(false);
}
然后分开:
public async Task<WhateverSIs> populateEntity(WhateverSIs s)
{
s.Entity = await parser.GetSiteDataAsync(s.Entity).ConfigureAwait(false);
return s;
}
我们不会明确创建任何Tasks
- 我们只使用async
方法公开的方法,包括GetSiteDataAsync
。