据我所知,没有办法知道它特别是发生了超时。我不是在寻找合适的地方,还是我错过了更大的东西?
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);
}
返回:
发生了一个或多个错误。
任务被取消了。
答案 0 :(得分:56)
您需要等待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);
}
答案 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 changed。 HttpClient
仍会抛出 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)};
通常是我做的,对我来说似乎很不错,尤其是在使用代理服务器时。