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.