如何判断HttpClient何时超时?

时间:2012-05-11 08:22:47

标签: c# timeout dotnet-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);
}

返回:

  

发生了一个或多个错误。

     

任务被取消了。

7 个答案:

答案 0 :(得分:56)

您需要等待GetAsync方法。如果它超时,它将抛出TaskCanceledException。此外,GetStringAsyncGetStreamAsync在内部处理超时,因此它们永远不会抛出。

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

答案 1 :(得分:52)

我正在重现同样的问题,这真的很烦人。我发现这些很有用:

HttpClient - dealing with aggregate exceptions

Bug in HttpClient.GetAsync should throw WebException, not TaskCanceledException

一些代码,以防链接无处可寻:

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

答案 2 :(得分:20)

我发现确定服务调用是否超时的最佳方法是使用取消令牌而不是HttpClient的超时属性:

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

然后在服务调用期间处理CancellationException ...

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

当然,如果超时发生在服务端,那么应该可以通过WebException来处理。

答案 3 :(得分:14)

从 .NET 5 开始,the implementation has changedHttpClient 仍会抛出 TaskCanceledException,但现在将 TimeoutException 包装为 InnerException。因此,您可以轻松检查请求是否已取消或超时(从链接的博客文章中复制的代码示例):

try
{
    using var response = await _client.GetAsync("http://localhost:5001/sleepFor?seconds=100");
}
// Filter by InnerException.
catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
{
    // Handle timeout.
    Console.WriteLine("Timed out: "+ ex.Message);
}
catch (TaskCanceledException ex)
{
    // Handle cancellation.
    Console.WriteLine("Canceled: " + ex.Message);   
}

答案 4 :(得分:8)

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

  

域名系统(DNS)查询最多可能需要15秒才能返回或超时。如果您的请求包含需要解决的主机名,并且您将Timeout设置为小于15秒的值,则可能需要15秒或更长时间才能抛出WebException以指示请求超时。< / p>

然后,您可以访问Status媒体资源,请参阅WebExceptionStatus

答案 5 :(得分:5)

基本上,你需要抓住jslint并检查传递给OperationCanceledException(或SendAsync,或任何GetAsync方法'的取消令牌的状态重新使用):

  • 如果取消(HttpClient为真),则表示请求确实已取消
  • 如果没有,则表示请求超时

当然,这不是很方便......如果超时,最好收到IsCancellationRequested。我在此提出了一个基于自定义HTTP消息处理程序的解决方案:Better timeout handling with HttpClient

答案 6 :(得分:3)

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

通常是我做的,对我来说似乎很不错,尤其是在使用代理服务器时。

相关问题