异步/等待,TaskEx.WhenAll和exceptions
本文关键字:WhenAll exceptions TaskEx 等待 异步 | 更新日期: 2023-09-27 18:10:51
这只是一个虚构的问题,我希望这个解决方案能在类似的场景中有所帮助。假设我需要计算网页上所有外部资源(图像,脚本等)的总大小。我下载页面,提取所有SRC信息,并将URL列表转换为下载任务:
async Task<int> GetTotalSize(Uri uri) {
string[] urls = ... code to extract all external resources' URLs from given page ...
var tasks = from url in urls.Distinct()
select new WebClient().DownloadDataTaskAsync(new Uri(url));
var files = await TaskEx.WhenAll(tasks);
return files.Sum(file => file.Length);
}
现在,如果其中一个链接由于任何原因无法访问,整个TaskEx。WhenAll被webeexception终止。我需要的是忽略单个任务中的任何webeexception,并假设在这种情况下长度为0。什么好主意吗?
只需添加一个单独的(异步)方法来获取单个url的大小。然后加起来。
。
static async Task<int> GetTotalSizeAsync(params string[] urls)
{
if (urls == null)
return 0;
var tasks = urls.Select(GetSizeAsync);
var sizes = await TaskEx.WhenAll(tasks);
return sizes.Sum();
}
static async Task<int> GetSizeAsync(string url)
{
try
{
var str = await new WebClient().DownloadStringTaskAsync(url);
return str.Length;
}
catch (WebException)
{
return 0;
}
}
此解决方案允许异步和并行执行,而目前接受的Jeff的回答不允许。
var tasks = from url in urls.Distinct()
select new WebClient().DownloadDataTaskAsync(new Uri(url));
try
{
await TaskEx.WhenAll(tasks);
}
catch(Exception)
{
}
var files = tasks
.Where(f => !f.IsFaulted)
.Select(f => f.Result);
return files.Sum(file => file.Length);
源自https://stackoverflow.com/a/15857555/1152054
我不认为你可以用上面的例子来避免aggregateexception——aggregateexception是有意义的,因为异常也可能是由非webbeexception引起的,例如取消。我认为正确的模式应该是用try catch块优雅地处理异常,如果"file"没有异常,则总结它。Reed有一个很好的帖子解释了同样的http://reedcopsey.com/2010/07/19/parallelism-in-net-part-18-task-continuations-with-multiple-tasks/
希望有所帮助