HttpClient-タスクはキャンセルされましたか?


191

1つまたは2つのタスクがある場合は正常に動作しますが、複数のタスクがリストされている場合は、「タスクがキャンセルされました」というエラーがスローされます。

ここに画像の説明を入力してください

List<Task> allTasks = new List<Task>();
allTasks.Add(....);
allTasks.Add(....);
Task.WaitAll(allTasks.ToArray(), configuration.CancellationToken);


private static Task<T> HttpClientSendAsync<T>(string url, object data, HttpMethod method, string contentType, CancellationToken token)
{
    HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, url);
    HttpClient httpClient = new HttpClient();
    httpClient.Timeout = new TimeSpan(Constants.TimeOut);

    if (data != null)
    {
        byte[] byteArray = Encoding.ASCII.GetBytes(Helper.ToJSON(data));
        MemoryStream memoryStream = new MemoryStream(byteArray);
        httpRequestMessage.Content = new StringContent(new StreamReader(memoryStream).ReadToEnd(), Encoding.UTF8, contentType);
    }

    return httpClient.SendAsync(httpRequestMessage).ContinueWith(task =>
    {
        var response = task.Result;
        return response.Content.ReadAsStringAsync().ContinueWith(stringTask =>
        {
            var json = stringTask.Result;
            return Helper.FromJSON<T>(json);
        });
    }).Unwrap();
}

内部例外は何と言っていますか?
RagtimeWilly 2015年

1
なぜあなたはCancellationTokenパラメータとして使用し、それを使用しないのですか?
ジム・アホ

1
私の理由はHttpClient、誤って処分したことasync Task<HttpResponseMessage> Method(){ using(var client = new HttpClient()) return client.GetAsync(request); }
でした

3
HttpClient@JobaDinizのように(using())を使用している場合は、停止してください。理由:aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
フィリップ

回答:


272

TaskCanceledExceptionスローされる理由は2つ考えられます。

  1. タスクが完了する前に、キャンセルトークンに関連付けられたものが呼び出さCancel()れましたCancellationTokenSource
  2. リクエストがタイムアウトした、つまりで指定した期間内に完了しなかったHttpClient.Timeout

それはタイムアウトだったと思います。(明示的なキャンセルである場合は、おそらくそれを理解しているでしょう。)例外を調べることで、より確実にすることができます。

try
{
    var response = task.Result;
}
catch (TaskCanceledException ex)
{
    // Check ex.CancellationToken.IsCancellationRequested here.
    // If false, it's pretty safe to assume it was a timeout.
}

3
それで、可能な解決策は何ですか?同様の問題があります。stackoverflow.com/questions/36937328/…–
開発者

48
@Dimi -これはかなり古いですが、私が使用した溶液は、より大きな値にTimeoutプロパティを設定することでした:httpClient.Timeout = TimeSpan.FromMinutes(30)
RQDQ

2
@RQDQ、あなたは男、男!コンストラクタを使用しないことで問題は解決しました。私の特定のケースでは、ミリ秒単位のタイムアウトが必要でした。御馳走TimeSpan.FromMilliseconds(Configuration.HttpTimeout)new TimeSpan(Configuration.HttpTimeout)働いたとは対照的に使用します。ありがとう!
Victor Ude 2017年

6
@RQDQ httpClient.Timeout = TimeSpan.FromMinutes(30)は、その特定のスレッドを30分間ブロックし、HTTPエンドポイント(主なタスク)にヒットしないため、良い方法ではありません。また、プログラムが30分前に終了した場合、遭遇する可能性が最も高くなりますThreadAbortException。より良いアプローチは、HTTPエンドポイントがヒットしていない理由を見つけることです。VPNまたは何らかの制限されたネットワークアクセスが必要になる場合があります。
Amit Upadhyay 2018

6
@AmitUpadhyay呼び出しがawaitedの場合、ブロックされているスレッドはありません。UIスレッド、スレッドプールスレッド、その他のバックグラウンドスレッドではありません。
Todd Menier、2018

20

私のMain()メソッドが戻る前にタスクが完了するのを待っていなかったためにこの問題に遭遇しTask<HttpResponseMessage> myTask、コンソールプログラムが終了したときにキャンセルされていました。

解決策はmyTask.GetAwaiter().GetResult()Main()この回答から)呼び出すことでした。


9

別の可能性は、クライアント側で結果が待たれないことです。これは、コールスタックのいずれかのメソッドがawaitキーワードを使用して、呼び出しが完了するまで待機しない場合に発生する可能性があります。


7
var clientHttp = new HttpClient();
clientHttp.Timeout = TimeSpan.FromMinutes(30);

上記は、大きなリクエストを待つための最良のアプローチです。あなたは約30分混乱しています。それはランダムな時間であり、あなたは好きな時間を与えることができます。

つまり、リクエストが30分前に結果を取得した場合、リクエストは30分間待機しません。30分は、リクエストの処理時間が30分であることを意味します。エラー「タスクがキャンセルされました」、または大量のデータ要求が発生した場合。


0

別の理由としては、サービス(API)を実行していて、サービスにブレークポイントを設定している(そしてコードがいくつかのブレークポイントで止まっている(たとえば、Visual StudioソリューションがRunningではなくDebuggingを表示している))ことが考えられます。次に、クライアントコードからAPIにアクセスします。したがって、サービスがブレークポイントで一時停止した場合、VSでF5キーを押すだけです。


0

私の状況では、コントローラーメソッドは非同期として作成されておらず、コントローラーメソッド内で呼び出されるメソッドは非同期でした。

したがって、このような問題を回避するには、async / awaitを最上位まで使用することが重要だと思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.