2017-04-07 23 views
0

多くのURLを同時に照会し、Task.WhenAll()を使用して応答を待つWebスクレーパーを作成しようとしています。しかし、タスクの1つが失敗した場合、WhenAllは失敗します。タスクの多くが404を返すことを期待しており、それらを処理または無視したいと考えています。たとえば:Task.WhenAll内のタスクのエラー処理

string urls = Enumerable.Range(1, 1000).Select(i => "https://somewebsite.com/" + i)); 
List<Task<string>> tasks = new List<Task<string>>(); 
foreach (string url in urls) 
{ 
    tasks.Add(Task.Run(() => { 
     try 
     { 
      return (new HttpClient()).GetStringAsync(url); 
     } 
     catch (HttpRequestException) 
     { 
      return Task.FromResult<string>(""); 
     } 
    })); 
} 
var responseStrings = await Task.WhenAll(tasks); 

これは決しては、catchステートメントを打つ、と私は例外を無視して、正常に完了したタスクを返すためにWhenAll取得できますかWhenAllは、最初の404で失敗しますか?さらに良い方法は、以下のコードのどこかで行うことができますか?

var tasks = Enumerable.Range(1, 1000).Select(i => (new HttpClient()).GetStringAsync("https://somewebsite.com/" + i)))); 
var responseStrings = await Task.WhenAll(tasks); 

ありがとうございました。

答えて

0

あなたは例外を観察するawaitを使用する必要があります。

var tasks = Enumerable.Range(1, 1000).Select(i => TryGetStringAsync("https://somewebsite.com/" + i)); 
var responseStrings = await Task.WhenAll(tasks); 
var validResponses = responseStrings.Where(x => x != null); 

private async Task TryGetStringAsync(string url) 
{ 
    try 
    { 
    return await httpClient.GetStringAsync(url); 
    } 
    catch (HttpRequestException) 
    { 
    return null; 
    } 
} 
+0

こんにちはスティーブン、ご回答に感謝を。以前のコードでは、GetAsync呼び出しを待っていましたが、すべてのタスクを実行して返すには時間がかかりすぎるようでした。次のタスクを作成する前に各タスクを待っているようでした。それはここで問題にならないだろうか? – Zaataro

+0

いいえ。このコードは同時に実行されます。詳細は、my ['async'イントロ](https://blog.stephencleary.com/2012/02/async-and-await.html)を参照してください。 –

+0

ありがとう!あなたのコードをテストしたところ、約200分の作業を完了するのに約1分かかっていました。これらが本当に非同期で並行していた場合、最後の作業はWebページを取得するのに一分間かかりましたか? – Zaataro

関連する問題