C#は素人なのでよくわかりません。
PHPerなので非同期もよくわかりません。
よくわからないの二乗でさっぱりわかりません。
やりたいことはタイトルどおりなんだけど、PHPで書くとこうです。
// URL
$urls = {
"https://example/com/a",
"https://example/com/b",
"https://example/com/c",
……
}
$client = new \GuzzleHttp\Client();
$promises = [];
// リクエスト出す
foreach ($urls as $url) {
$promises[] = $client->getAsync($url);
}
// 全部終わるまで待つ
$responses = \GuzzleHttp\Promise\all($promises)->wait();
これをAzure Functionsとかでやりたかったわけです。
探してみたんだけど、何故か複数リクエストを出す場合という情報が全然見当たりません。
よく見かける実装だとawait HttpClient.GetAsync(url)
とかなんだけど、これだとURLひとつひとつにリクエストするたびに待機するってことだよね?
ようやくここでそれっぽいのを見つけたので、これを参考に作った。
// URL
string[] urls = {
"https://example/com/a",
"https://example/com/b",
"https://example/com/c",
……
}
var client = new HttpClient();
List<Task> promises = new List<Task>();
// リクエストを投げる
foreach (string url in urls) {
promises.Add(client.GetAsync(url));
}
// 全部終わるまで待つ
Task.WaitAll(promises.ToArray());
さて、とりあえずこれで一応動いたんだけど、本当にこれが適切な実装なのかはよくわからない。
どうもこのあたりを見るとSNATが爆発しそうな気配を感じるのですが、ではどうすればいいのかがよくわかりません。
HttpClientHandler.MaxConnectionsPerServerを指定すればいいのか、そうするとそれ以上のリクエストは待たされるのか破棄されるのか。
そもそもPHPだったころは何も考えなくてもSNAT問題とか起きたことがないんだけど、どうしてC#になった途端に死ぬのか。
Task.WaitAll()
とawait Task.WhenAll()
の違いもわかりません。
あとどうしてこれがデッドロックするのか全くわからない。
調べればわかるのかもしれないけど面倒になったので解決もせずにここで終わり。