web-dev-qa-db-ja.com

HttpClientがタイムアウトしたことを確認するにはどうすればよいですか?

私が知る限り、それが特にタイムアウトが発生したことを知る方法はありません。適切な場所を見ていませんか、それとももっと大きなものを見逃していますか?

string baseAddress = "http://localhost:8080/";
var client = new HttpClient() 
{ 
    BaseAddress = new Uri(baseAddress), 
    Timeout = TimeSpan.FromMilliseconds(1) 
};
try
{
    var s = client.GetAsync("").Result;
}
catch(Exception e)
{
    Console.WriteLine(e.Message);
    Console.WriteLine(e.InnerException.Message);
}

これは返します:

1つ以上のエラーが発生しました。

タスクがキャンセルされました。

116
Benjol

GetAsyncメソッドを待つ必要があります。タイムアウトになった場合、TaskCanceledExceptionをスローします。さらに、GetStringAsyncおよびGetStreamAsyncは内部的にタイムアウトを処理するため、決してスローされません。

string baseAddress = "http://localhost:8080/";
var client = new HttpClient() 
{ 
    BaseAddress = new Uri(baseAddress), 
    Timeout = TimeSpan.FromMilliseconds(1) 
};
try
{
    var s = await client.GetAsync();
}
catch(Exception e)
{
    Console.WriteLine(e.Message);
    Console.WriteLine(e.InnerException.Message);
}
58
murkaeus

私は同じ問題を再現していますが、本当に迷惑です。私はこれらが便利だと感じました:

HttpClient-集約例外の処理

HttpClient.GetAsyncのバグはTaskCanceledExceptionではなくWebExceptionをスローする必要があります

リンクがどこにも行かない場合のコード:

var c = new HttpClient();
c.Timeout = TimeSpan.FromMilliseconds(10);
var cts = new CancellationTokenSource();
try
{
    var x = await c.GetAsync("http://linqpad.net", cts.Token);  
}
catch(WebException ex)
{
    // handle web exception
}
catch(TaskCanceledException ex)
{
    if(ex.CancellationToken == cts.Token)
    {
        // a real cancellation, triggered by the caller
    }
    else
    {
        // a web request timeout (possibly other things!?)
    }
}
53
vezenkov

サービスコールがタイムアウトしたかどうかを判断する最善の方法は、HttpClientのタイムアウトプロパティではなくキャンセルトークンを使用することであることがわかりました。

var cts = new CancellationTokenSource();
cts.CancelAfter(timeout);

そして、サービス呼び出し中にCancellationExceptionを処理します...

catch(TaskCanceledException)
{
    if(!cts.Token.IsCancellationRequested)
    {
        // Timed Out
    }
    else
    {
        // Cancelled for some other reason
    }
}

もちろん、サービス側でタイムアウトが発生した場合、WebExceptionで処理できるはずです。

20
Jack

から http://msdn.Microsoft.com/en-us/library/system.net.http.httpclient.timeout.aspx

ドメインネームシステム(DNS)クエリが返されるか、タイムアウトになるまでに最大15秒かかる場合があります。リクエストに解決が必要なホスト名が含まれていて、タイムアウトを15秒未満の値に設定すると、15秒以上かかる場合がありますリクエストのタイムアウトを示すためにWebExceptionがスローされます

次に、Statusプロパティにアクセスします。 WebExceptionStatus を参照してください

8
user247702

基本的に、OperationCanceledExceptionをキャッチし、SendAsync(またはGetAsync、または使用しているHttpClientメソッドに渡されたキャンセルトークンの状態を確認する必要があります。 :

  • キャンセルされた場合(IsCancellationRequestedがtrue)、それはリクエストが本当にキャンセルされたことを意味します
  • そうでない場合、リクエストがタイムアウトしたことを意味します

もちろん、これはあまり便利ではありません...タイムアウトの場合はTimeoutExceptionを受け取る方が良いでしょう。ここでは、カスタムHTTPメッセージハンドラーに基づいたソリューションを提案します。 HttpClientでのタイムアウト処理の改善

5
Thomas Levesque
_httpClient = new HttpClient(handler) {Timeout = TimeSpan.FromSeconds(5)};

私が普段やっていることは、私にとってはかなりうまくいくようです。プロキシを使用する場合は特に良いです。

3
Syv Development