3

This is just an imaginary problem, I'm hoping that the solution will help in whole range of similar scenarios. Suppose I need to count total size of all external resources on a webpage (images, scripts etc.). I download the page, extract all SRC information and transform the URL list into download tasks:

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);
}

Now, if one of the links is unreachable for any reason, the whole TaskEx.WhenAll is aborted with WebException. What I need is to ignore any WebExceptions inside individual tasks and assume length of 0 in that case. Any ideas?

4

3 回答 3

5

只需添加一个单独的(异步)方法来获取单个 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;
    }
}
于 2011-10-09T08:51:28.200 回答
3

该解决方案允许异步和并行执行,而 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

于 2014-02-07T17:33:24.777 回答
0

我认为您不能通过上面的示例避免聚合异常 - 聚合异常是有道理的,因为异常也可能是由非 Web 异常引起的,例如取消。我相信正确的模式应该是使用 try catch 块优雅地处理异常,如果“文件”没有异常,请总结一下。里德有一篇很好的帖子解释了同样的http://reedcopsey.com/2010/07/19/parallelism-in-net-part-18-task-continuations-with-multiple-tasks/

希望能帮助到你

于 2011-10-09T08:51:15.453 回答