HttpClient가 시간 초과되었음을 어떻게 알 수 있습니까?


142

내가 알 수있는 한, 그것이 특별히 타임 아웃 된 것을 알 수있는 방법은 없습니다. 올바른 장소를 보지 않습니까, 아니면 더 큰 것을 놓치고 있습니까?

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);
}

이것은 다음을 반환합니다.

하나 이상의 오류가 발생했습니다.

작업이 취소되었습니다.


3
우리는 GitHub에 대한 문제를 공감할 수
— csrowell

질문에 대한 큰 공감대. 또한 ... UWP 에서이 작업을 수행하는 방법에 대한 아이디어가 있습니까? Windows.Web.HTTP.HTTPClient에 시간 초과 멤버가 없습니다. 또한 GetAsync 메소드는 취소 토큰을 허용하지 않습니다 ...
— Do-do-new

1
6 년 후에도 클라이언트가 시간 초과되었는지 알 수없는 것 같습니다.
— Steve Smith

답변:


61

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);
}

2
나는 이것을 테스트 하고 나를 위해 GetStreamAsync던졌다 TaskCanceledException.
— Sam

38
TaskCanceledException직접 취소 또는 기타 이유로 말하지 않고 HTTP 시간 초과로 인한 것인지 어떻게 알 수 있습니까?
— UserControl

8
@UserControl 확인 TaskCanceledException.CancellationToken.IsCancellationRequested. False 인 경우 제한 시간이 초과되었다고 확신 할 수 있습니다.
— Todd Menier

3
알고 보니, 당신은 믿을 수없는 IsCancellationRequested설정을 점점 내가 이전에 생각으로 직접 취소에 토큰 예외의 : stackoverflow.com/q/29319086/62600
— 토드 미니 어

2
@testing 그들은 다르게 행동 하지 않습니다 . 사용자 취소 요청을 나타내는 하나의 토큰과 클라이언트 시간 초과를 나타내는 내부 (액세스 할 수없고 필요하지 않은) 토큰 만 있으면됩니다. 사용 사례가 다릅니다
— Rufo

59

나는 같은 문제를 재현하고 있으며 실제로 성가시다. 나는 이것들이 유용하다는 것을 알았다.

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!?)
    }
}

내 경험상 WebException은 어떤 상황에서도 잡힐 수 없습니다. 다른 사람들이 다른 것을 경험하고 있습니까?
— 16:24에

1
@crush를 잡을 WebException 수 있습니다. 아마도 이것이 도움 이 될 것입니다.
— DavidRR

cts를 사용하지 않으면 이것은 효과가 없습니다. 방금 Task <T> task = SomeTask () try {T result = task.Result} catch (TaskCanceledException) {} catch (Exception e) {}을 사용하고 있습니다. TaskCanceledException이 아니라 일반적인 예외 만 포착됩니다. 내 코드 버전에 어떤 문제가 있습니까?
— 나오미

1
원본 버그는 보관 된 포럼 게시물에있는 것으로 보이므로 새 버그 보고서를 만들었습니다. connect.microsoft.com/VisualStudio/feedback/details/3141135
— StriplingWarrior

1
토큰이 외부에서 전달 default(CancellationToken)되면와 비교하기 전에 토큰을 검사하지 않습니다 ex.CancellationToken.
— SerG

25

서비스 호출 시간이 초과되었는지 확인하는 가장 좋은 방법은 HttpClient의 시간 초과 속성이 아닌 취소 토큰을 사용하는 것입니다.

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

그런 다음 서비스 호출 중에 CancellationException을 처리하십시오 ...

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

물론 타임 아웃이 서비스 측에서 발생하면 WebException으로 처리 할 수 ​​있습니다.


1
흠, 나는이 샘플이 이해하기 위해 부정 연산자 (편집에 추가 된)를 제거해야한다고 생각합니다. 경우 cts.Token.IsCancellationRequested이다 true가 시간 초과가 발생했습니다 것을 의미 하는가?
— Lasse Christiansen

9

에서 http://msdn.microsoft.com/en-us/library/system.net.http.httpclient.timeout.aspx

DNS (Domain Name System) 쿼리가 반환되거나 시간 초과되는 데 최대 15 초가 걸릴 수 있습니다. 요청에 해결이 필요한 호스트 이름이 포함되어 있고 제한 시간을 15 초 미만으로 설정하면 요청에서 제한 시간을 표시 하기 위해 WebException이 발생 하기까지 15 초 이상 걸릴 수 있습니다 .

그런 다음 Status속성에 액세스 하십시오. WebExceptionStatus를 참조하십시오.


3
흠, 나는 내부 AggregateException와 함께 돌아오고 있어요 TaskCancelledException. 내가 뭔가 잘못하고 있어야합니다 ...
— Benjol

사용하고 catch(WebException e)있습니까?
— user247702

아니, 내가 시도하면 AggregateException처리되지 않습니다. VS 콘솔 프로젝트를 작성하는 경우 참조를 추가 System.Net.Http하고 코드를에 삽입 main하면 원하는 경우 직접 확인할 수 있습니다.
— Benjol

5
대기 기간이 작업의 시간 초과 기간을 초과하면가 표시 TaskCanceledException됩니다. 이것은 TPL의 내부 시간 초과 처리에 의해보다 높은 수준에서 발생하는 것으로 보입니다 HttpWebClient. 이 좋은 방법이 될 것 같지 않습니다 시간 제한 취소 및 사용자의 취소를 구별 할 수 있습니다. 이것의 결과는 당신이 당신의 WebException안에 얻을 수 없다는 것 AggregateException입니다.
— JT.

1
다른 사람들이 말했듯이 TaskCanceledException이 시간 초과라고 가정해야합니다. try {// Code here} catch (AggregateException exception) {if (exception.InnerExceptions.OfType <TaskCanceledException> (). Any ()) {// Handle timeout here}}
— Vdex

8

기본적으로, 당신 OperationCanceledException은 전달 된 취소 토큰의 상태를 확인 해야합니다 SendAsync(또는 사용중인 GetAsync모든 HttpClient방법).

  • 취소 된 경우 (IsCancellationRequested true) 요청이 실제로 취소되었음을 의미합니다.
  • 그렇지 않은 경우 요청 시간이 초과되었음을 의미합니다.

물론 이것은 매우 편리하지 않습니다 ... TimeoutException시간 초과의 경우 수신하는 것이 좋습니다 . 커스텀 HTTP 메시지 핸들러를 기반으로 여기에 솔루션을 제안합니다 : HttpClient로 더 나은 시간 초과 처리


아! 너야! 오늘 초 블로그 포스트에 의견을 썼습니다. 그러나이 답변에 비추어 볼 때, 나는 스스로 취소하지 않았을 때 그것이 항상 진실 인 것처럼 보이기 때문에 IsCancellationRequested에 대한 당신의 요점이 사실이 아니라고 생각합니다
— knocte

그것은 또한이에 의존하기 때문에 @knocte, 그 이상 하네 ...하지만 그 경우에, 내 블로그 게시물의 솔루션은 도움이되지 않습니다
— 토마스 레베

1
이것에 대한 github 문제에서 많은 사람들은 내가 말한 것을 주장합니다 : IsCancellationRequested는 시간 초과가있을 때 참입니다. 그래서 나는 당신의 대답을 downvote하고 싶습니다;)
— knocte

@knocte, 나는 당신에게 무엇을 말 해야할지 모르겠다 ... 나는 이것을 오랫동안 사용 해 왔으며 항상 나를 위해 일했다. HttpClient.Timeout무한대로 설정 했습니까 ?
— Thomas Levesque

나 자신을 제어 HttpClient를 할 수 없기 때문에 아니, 난하지 않았다, 내가 그 용도 그것의 하나를 사용하고있는 타사 라이브러리입니다
— knocte

-1
_httpClient = new HttpClient(handler) {Timeout = TimeSpan.FromSeconds(5)};

내가 일반적으로하는 일, 꽤 잘 작동하는 것 같습니다. 프록시를 사용할 때 특히 좋습니다.


1
이것이 httpclient의 시간 초과를 설정하는 방법입니다. 이것은 httpclient가 시간 초과되었을 때 어떻게 알 수 있었는지 질문을 다루지 않습니다.
— Ethan Fischer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.