3

これは単なる架空の問題であり、このソリューションが同様のシナリオのすべての範囲で役立つことを願っています。Webページ上のすべての外部リソース(画像、スクリプトなど)の合計サイズをカウントする必要があるとします。ページをダウンロードし、すべての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);
}

これで、何らかの理由でリンクの1つに到達できない場合、TaskEx.WhenAll全体がWebExceptionで中止されます。私が必要としているのは、個々のタスク内のWebExceptionを無視し、その場合は長さ0を想定することです。何か案は?

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

このソリューションでは、非同期実行と並列実行の両方が可能ですが、現在ジェフから受け入れられている回答では不可能です。

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

上記の例では、aggregateexceptionを回避できないと思います。aggregateexceptionは、キャンセルなどの非webexceptionによっても例外が発生する可能性があるため、意味があります。正しいパターンは、try catchブロックを使用して例外を適切に処理することであり、「ファイル」に例外がない場合はそれを合計する必要があると思います。リードには、まったく同じhttp://reedcopsey.com/2010/07/19/parallelism-in-net-part-18-task-continuations-with-multiple-tasks/を説明する素晴らしい投稿があります。

それが役に立てば幸い

于 2011-10-09T08:51:15.453 に答える