在处理WhenAll时优雅地处理异常

lin*_*rro 1 c# async-await

我正在玩一段我写的代码片段.这段代码处理以异步方式发出一些请求.

var client = new HttpClient();

var searchPromises = searchTerms
    .Select(GetSearchUrl)
    .Select(client.GetStringAsync);
var searchPages = await Task.WhenAll(searchPromises);
Run Code Online (Sandbox Code Playgroud)

发生的事情是我创建一个新的HttpClient.使用一些搜索引擎术语我组成搜索引擎网址.然后我使用这些URL作为输入来获取表示具有结果的页面的异步请求的任务.最后,我等待那些回复用于Task.WhenAll将它们组合在一起.

问题是,如果其中一个请求获得404,500或类似我的代码抛出的任何东西AggregateException.

是否有一种方法可以指定在其中一个线程中出现错误时应该发生什么,以便从其他所有内容中获得结果?

我看过ContinueWith,但它似乎不符合要求,也就是说,它不知道如何处理所有错误,只是汇总错误.

Ste*_*ary 6

会发生什么是我创建一个新的HttpClient.使用一些搜索引擎术语我组成搜索引擎网址.然后我使用这些URL作为输入来获取表示具有结果的页面的异步请求的任务.最后,我等待使用Task.WhenAll将这些响应组合在一起的响应.

是否有一种方法可以指定在其中一个线程中出现错误时应该发生什么,以便从其他所有内容中获得结果?

IMO,最简单的解决方案是改变您对问题的看法.现在,您正在考虑"在每个网址上执行下载",然后"为他们所有人完成并根据每个项目处理错误".只需更改您的操作("下载")即可包含您想要按项目执行的任何操作.换句话说,你想要做的是"在每个网址上执行下载并处理错误",然后"等待它们全部完成":

var client = new HttpClient();
var searchPromises = searchTerms
  .Select(GetSearchUrl)
  .Select(url => DownloadAsync(client, url));
var searchPages = await Task.WhenAll(searchPromises);
var successfulSearchPages = searchPages.Where(x => x != null);

...

private static async Task<string> DownloadAsync(HttpClient client, string url)
{
  try
  {
    return await client.GetStringAsync(url);
  }
  catch (HttpRequestException ex)
  {
    // TODO: Perform appropriate error handling
    return null;
  }
}
Run Code Online (Sandbox Code Playgroud)