web-dev-qa-db-ja.com

HttpClient-タスクはキャンセルされました-正確なエラーメッセージを取得する方法は?

次のテストコードがあります。 316934または361992回ループした後、「タスクがキャンセルされました」というエラーが常に表示されます。

私が間違っていない場合、タスクがキャンセルされた理由は2つあります。a)HttpClientがタイムアウトしたか、b)キュー内のタスクが多すぎて、一部のタスクがタイムアウトしました。

タスクのキューイングの制限に関するドキュメントが見つかりませんでした。そして、50万以上のタスクを作成し、タイムアウトは作成しませんでした。理由「b」が正しくない可能性があります。

Q1。私が逃した他の理由はありますか?

Q2。 HttpClientのタイムアウトが原因である場合、「TaskCancellation」例外の代わりに正確な例外メッセージを取得する方法を教えてください。

Q3。それを修正する最良の方法は何でしょうか?スロットルを導入する必要がありますか?

ありがとう!

var _httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "text/html,application/xhtml+xml,application/xml");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Encoding", "gzip, deflate");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Charset", "ISO-8859-1");

int[] intArray = Enumerable.Range(0, 600000).ToArray();

var results = intArray                
    .Select(async t => {

        using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, "http://www.google.com")) {
            log.Info(t);

            try {

                var response = await _httpClient.SendAsync(requestMessage);
                var responseContent = await response.Content.ReadAsStringAsync();

                return responseContent;
            }
            catch (Exception ex) {
                log.ErrorException(string.Format("SoeHtike {0}", Task.CurrentId), ex);
            }
            return null;
        }
    });

Task.WaitAll(results.ToArray());

Console.ReadLine();

問題を再現する手順は次のとおりです。

  1. VS 2012でコンソールプロジェクトを作成します。

  2. メインにコードをコピーして貼り付けてください。

  3. この行にブレークポイントを配置します "log.ErrorException(string.Format(" SoeHtike {0} "、Task.CurrentId)、ex);"

プログラムをデバッグモードで実行します。数分待ちます。 (たぶん5分?)コードをテストしたところ、3分後に例外が発生しました。フィドラーがある場合は、要求を監視して、プログラムがまだ実行されているかどうかを確認できます。

問題を再現できない場合は、お気軽にお知らせください。

51
Michael Sync

デフォルト HttpClient.Timeout値は100秒(00:01:40)です。 catchブロックでタイムスタンプを実行すると、その時点でタスクがキャンセルされ始めることがわかります。 1秒間に実行できるHTTPリクエストの数は限られているようですが、他のHTTPリクエストはキューに入れられます。キューに入れられたリクエストはタイムアウトでキャンセルされます。私が個人的に成功させたタスクは60万件ありますが、他のタスクはキャンセルされました。

また、600000のタスク全体を実行できる可能性は低いと思います。多くのネットワークドライバーは、短時間で多数の要求を許可し、しばらくしてその数を非常に低い値に減らします。ネットワークカードを使用すると、36秒以内に921リクエストのみを送信でき、その速度は1秒間に1リクエストにまで低下しました。その速度では、すべてのタスクを完了するのに1週間かかります。

その制限を回避できる場合は、アプリがメモリを非常に消費しているため、64ビットプラットフォーム用のコードをビルドしてください。

64
Dmitri Trofimov

使用しているHttpClientのインスタンスを破棄しないでください。奇妙だが、私にとってはこの問題を修正した。

34
abatishchev

ただ共有したかったのですが、サーバーの負荷テストを行うための同様のコードがあり、リクエストがタイムアウトする可能性が高いです。 httpリクエストのタイムアウトをmaxに設定し、それが何かを変更するかどうかを確認できます。さまざまなスレッドを作成してサーバーにアクセスしてみました。また、ヒットは増加しましたが、最終的にはすべてタイムアウトになります。また、別のスレッドでヒットしたときにタイムアウトを設定することもできません。

1
Andy Khatter