2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【C#】たくさんHTTPリクエストを出して全て終わるまで待つ

Last updated at Posted at 2023-02-27

C#は素人なのでよくわかりません。
PHPerなので非同期もよくわかりません。
よくわからないの二乗でさっぱりわかりません。

やりたいことはタイトルどおりなんだけど、PHPで書くとこうです。

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ひとつひとつにリクエストするたびに待機するってことだよね?

ようやくここでそれっぽいのを見つけたので、これを参考に作った。

C#
	
	// 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()の違いもわかりません。
あとどうしてこれがデッドロックするのか全くわからない。

調べればわかるのかもしれないけど面倒になったので解決もせずにここで終わり。

2
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?