7

私はapi呼び出しのためにFileResult : IHttpActionResult webapi戻り値の型を作成しました。 FileResultは別のURLからファイルをダウンロードし、ストリームをクライアントに返します。HttpClientがステートメントを使用しています原因:タスクがキャンセルされました

public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
{ 
    try 
    { 
     HttpResponseMessage response; 
     using (var httpClient = new HttpClient()) 
     { 

      response = new HttpResponseMessage(HttpStatusCode.OK) 
      { 
       Content = new System.Net.Http.StreamContent(
            await httpClient.GetStreamAsync(this.filePath)) 
      }; 
     } 
     return response; 
    } 
    catch (WebException exception) 
    {...} 
} 

しかし、これは断続的にTaskCanceledExceptionを引き起こす:

は、最初は私のコードは以下のようなusing文を持っていました。私は、非同期呼び出しが終了する前にHttpClientが処分されると、タスクの状態がキャンセルに変わることを知っています。しかし、に入れてください:Content = new System.Net.Http.StreamContent(await httpClient.GetStreamAsync(this.filePath))これは、タスクの完了の途中でHttpClientが処分されるのを防ぐためです。

なぜこのタスクはキャンセルされますか?これはタイムアウトのためではありません。これは最小の要求で発生しており、大きな要求では必ずしも発生しないためです。私はusing文を削除する場合

は、コードが正常に働いていた:

public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
{ 
    try 
    { 
     HttpResponseMessage response; 
     var httpClient = new HttpClient(); 

     response = new HttpResponseMessage(HttpStatusCode.OK) 
     { 
      Content = new System.Net.Http.StreamContent(
           await httpClient.GetStreamAsync(this.filePath)) 
     }; 
     return response; 
    } 
    catch (WebException exception) 
    {...} 
} 

を使用して、なぜすべてのアイデアは、問題を引き起こしましたか?

+0

デバッガーを使用してみましたか?それを段階的にチェックする。 – kevintjuh93

+0

はい、あります。例外がここにスローされるのではなく、完全に異なる場所にあるので、実際には役に立ちません。これはOwinのパイプラインで発生します。私は認証がどこであり、次の要求を待っています。 – Rafi

+0

'TaskCanceledException'に内部例外がありますか? –

答えて

9

私は非同期呼び出しが完了する前にHttpClientが配置されている場合は、タスクの状態が解除に変更されていることを知っています。しかし、私は:Content = new System.Net.Http.StreamContent(httpClient.GetStreamAsync(this.filePath)を待つ)を待つので、HttpClientがタスクの完了の途中で中断するのを防ぐはずです。

しかし、このタスクは何をしますか?ストリームを取得します。したがって、あなたのコードはHttpClientを閉じるときに完全に読み込まれるかもしれないし、そうでないかもしれないStreamで終わる。

HttpClientは、具体的には、再利用(同時使用)のために設計されたので、私は完全にusingを除去しstaticクラスメンバへHttpClient宣言を移動させるお勧めしています。しかし、クライアントを閉じて再オープンしたい場合は、に読み込み、ストリームを完全にメモリに読み込んでからHttpClientを閉じる必要があります。

4

私はタスクキャンセルの例外で同様の問題がありました。あなたがAggregateExceptionをキャッチしたり、WebExceptionの下にキャッチにすべてExceptionブロックを持つしようとすると、あなたも、あなたが、私はいくつかの調査を行なったし、見つけ

を「タスクがキャンセルされた」旨のエントリで一つの例外を除いて、それをキャッチすることを見つけるかもしれませんAggregateExceptionは、さまざまなスレッドで説明されているようにかなり誤解を招きます。

Setting HttpClient to a too short timeout crashes process

How can I tell when HttpClient has timed out?

Bug in httpclientgetasync should throw webexception not taskcanceledexception

私は(asyncTimeoutInMinsは、app.configファイルから読み込まれる)明示的なタイムアウトを設定するには、私のコードを変更することになりました。

 string jsonResponse = string.Empty; 
     try 
     { 
      using (HttpClient httpClient = new HttpClient()) 
      { 
       httpClient.BaseAddress = new Uri(Properties.Settings.Default.MyWebService); 
       httpClient.DefaultRequestHeaders.Accept.Clear(); 
       httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 
       httpClient.Timeout = new TimeSpan(0, asyncTimeoutInMins, 0); 

       HttpResponseMessage response; 

       response = await httpClient.GetAsync("/myservice/resource"); 

       // Check the response StatusCode 
       if (response.IsSuccessStatusCode) 
       { 
        // Read the content of the response into a string 
        jsonResponse = await response.Content.ReadAsStringAsync(); 
       } 
       else if (response.StatusCode == HttpStatusCode.Forbidden) 
       { 
        jsonResponse = await response.Content.ReadAsStringAsync(); 

        Logger.Instance.Warning(new HttpRequestException(string.Format("The response StatusCode was {0} - {1}", response.StatusCode.ToString(), jsonResponse))); 

        Environment.Exit((int)ExitCodes.Unauthorised); 
       } 
       else 
       { 
        jsonResponse = await response.Content.ReadAsStringAsync(); 

        Logger.Instance.Warning(new HttpRequestException(string.Format("The response StatusCode was {0} - {1}", response.StatusCode.ToString(), jsonResponse))); 

        Environment.Exit((int)ExitCodes.ApplicationError); 
       } 
      } 

     } 
     catch (HttpRequestException reqEx) 
     { 
      Logger.Instance.Error(reqEx); 

      Console.WriteLine("HttpRequestException : {0}", reqEx.InnerException.Message); 

      Environment.Exit((int)ExitCodes.ApplicationError); 
     } 
     catch (Exception ex) 
     { 
      Logger.Instance.Error(ex); 

      throw; 
     } 

     return jsonResponse; 
+0

上記のコメントに記載されているように、例外は認証ロジックレイヤーには検出されません。 – Rafi