HttpClient throws TaskCanceledException on timeout
error msg:
HttpClient throws TaskCanceledException on timeout
HttpClient is throwing a TaskCanceledException on timeout in some circumstances. This is happening for us when the server is under heavy load. We were able to work around by increasing the default timeout. The following MSDN forum thread captures the essence of the experienced issue:
error code:
var c = new HttpClient();
try
{
c.Timeout = TimeSpan.FromMilliseconds(10);
var x = await c.GetAsync("http://linqpad.net");
}
catch(TaskCanceledException ex)
{
Console.WriteLine("should not see this type of exception!");
Console.WriteLine(ex.Message);
}
Surely this should be throwing a WebException? This behaviour makes it difficult to tell the difference between timeout exceptions & legit cancellations!
1.
Did you ever thik about doing what I did below?
var c = new HttpClient();
try
{
c.Timeout = TimeSpan.FromMilliseconds(10);
}
catch(TaskCanceledException ex)
{
Console.WriteLine("should not see this type of exception!");
Console.WriteLine(ex.Message);
}
try
{
var x = await c.GetAsync("http://linqpad.net");
}
catch(TaskCanceledException ex)
{
Console.WriteLine("should not see this type of exception!");
Console.WriteLine(ex.Message);
}
2.
Hmm. I'm not sure if you understand the problem (or I don't understand your answer!)
I've moved the code where I set the timeout. The TaskCanceledException is thrown from the call to GetAsync.
var c = new HttpClient();
c.Timeout = TimeSpan.FromMilliseconds(10);
try
{
var x = await c.GetAsync("http://linqpad.net");
}
catch(TaskCanceledException ex)
{
Console.WriteLine("should not see this type of exception!?");
Console.WriteLine(ex.Message);
}
I don't think this is a very good API. It shouldn't throw a TaskCanceledException unless the caller supplies a CancelationToken and calls Cancel! It should be a WebException.
3.
You code has four diffent Network layers where an error can occur
1) You first have to interface with a socket on the local computer.
2) A TCP connection has to complete from a socket with an IP address on your computer to an IP address on the server
3) On top of TCP and HTTP negotiation has to occur. You may need credentials (cookies, certifications, login) for this to complete.
4) Then the webpage has to run which sends data back to your computer.
Some of the above errors will actually return error strings, other errors may cause the application to hang causing a time out. Some errors will occur in less than 10msec. 10msec is one timer tick and the timer ticks on a computer don't run exactly at 10msec. If you are having an error that is occuring that quickly it is probably on yhour local host.
Try putting the URL into a webbrowser to see what errors you get with a webbrower. If the webbrowser works then you are mising an instruction in your code to use credentials. See this webpage
I'm not sure if you should be using the default credentials or using a specific proxy setting
4.
Hi Joel,
I'm sorry but I don't think you've understood the post. I know why the code throws an exception, it is because the HTTP request can't be serviced within the specified timeout period (if you increase the timeout the request is serviced). The post is about the type of exception that is being raised.
I'm suggesting that it shouldn't be a TaskCanceledException but a WebException!
Does that make sense?
5.
For me the point is that as good developers we check the msdn documentation for possible exceptions and catch only those. In this case we should actually be catching a WebException (http://msdn.microsoft.com/en-us/library/system.net.http.httpclient.timeout.aspx).
I guess what James is saying is that either the documentation is wrong or there is a bug. Unless, that is, theres some other documentation/rule/recommendation somewhere that recommends we warp all async calls in a try/catch(TaskCancelledException) and I doubt there is.
7.
Exactly! (Thanks Stelrad)
The caller should be provided with a detailed WebException.
*update* I've update the question replaced TimeoutException -> WebException
8.
Just to ram the point home... if you wanted to support cancellation and implement an interesting WebException handling routine (for example a retry policy), you might end up with the following abomination.
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!?)
}
}
I find it hard to believe that this is by design.
9.
Whether the right design or not, by design OperationCanceledExceptions are thrown for timeouts (and TaskCanceledException is an OperationCanceledException).
10.
Our team found this unintuitive, but it does seem to be working as designed. Unfortunately, when we hit this, we wasted a bit of time trying to find a source of cancelation. Having to handle this scenario differently from task cancelation is pretty ugly (we created custom handler to manage this). This also seems to be an overuse of cancelation as a concept.
Thanks again for thee quick response.
11.
This is a bad design IMO. There's no way to tell if the request was actually canceled (i.e. the cancellation token passed to SendAsync was canceled) or if the timeout was elapsed. In the latter case, it would make sense to retry, whereas in the former case it wouldn't. There's a TimeoutException that would be perfect for this case, why not use it?
12.
We have several options what to do when timeout happens:
- Throw
TimeoutExceptioninstead ofTaskCanceledException.- Pro: Easy to distinguish timeout from explicit cancellation action at runtime
- Con: Technical breaking change - new type of exception is thrown.
- Throw
TaskCanceledExceptionwith inner exception asTimeoutException- Pro: Possible to distinguish timeout from explicit cancellation action at runtime. Compatible exception type.
- Open question: Is it ok to throw away original
TaskCanceledExceptionstack and throw a new one, while preservingInnerException(asTimeoutException.InnerException)? Or should we preserve and just wrap the originalTaskCanceledException?- Either: new TaskCanceledException -> new TimeoutException -> original TaskCanceledException (with original InnerException which may be null)
- Or: new TaskCanceledException -> new TimeoutException -> original TaskCanceledException.InnerException (may be null)
- Throw
TaskCanceledExceptionwith message mentioning timeout as the reason- Pro: Possible to distinguish timeout from explicit cancellation action from the message / logs
- Con: Cannot be distinguished at runtime, it is "debug only".
- Open question: Same as in [2] - should we wrap or replace the original TaskCanceledException (and it stack)
I am leaning towards option [2], with discarding original stack of original TaskCanceledException.
@stephentoub @davidsh any thoughts?
BTW: The change should be fairly straightforward in HttpClient.SendAsync where we set up the timeout:
CancellationTokenSource cts;
bool disposeCts;
bool hasTimeout = _timeout != s_infiniteTimeout;
if (hasTimeout || cancellationToken.CanBeCanceled)
{
disposeCts = true;
cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _pendingRequestsCts.Token);
if (hasTimeout)
{
cts.CancelAfter(_timeout);
}
}
else
{
disposeCts = false;
cts = _pendingRequestsCts;
} // Initiate the send.
Task<HttpResponseMessage> sendTask;
try
{
sendTask = base.SendAsync(request, cts.Token);
}
catch
{
HandleFinishSendAsyncCleanup(cts, disposeCts);
throw;
}
.NET Framework also throws TaskCanceledException when you set HttpClient.Timeout.
HttpClient throws TaskCanceledException on timeout的更多相关文章
- HttpClient Timeout waiting for connection from pool 问题解决方案
错误:org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool 前言 ...
- HttpClient Timeout
1. Overview This tutorial will show how to configure a timeout with the Apache HttpClient 4. If you ...
- 1、揭秘通用平台的 HttpClient (译)
原文链接:Demystifying HttpClient APIs in the Universal Windows Platform 正打算翻译这篇文章时,发现园子里已经有朋友翻译过了,既然已经开始 ...
- HttpComponents组件探究 - HttpClient篇
在Java领域,谈到网络编程,可能大家脑海里第一反应就是MINA,NETTY,GRIZZLY等优秀的开源框架.没错,不过在深入探究这些框架之前,我们需要先从最original的技术探究开始(当然,需要 ...
- 基于HttpClient实现网络爬虫~以百度新闻为例
转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/40891791 基于HttpClient4.5实现网络爬虫请訪问这里:http:/ ...
- 转:轻松把玩HttpClient之封装HttpClient工具类(一)(现有网上分享中的最强大的工具类)
搜了一下网络上别人封装的HttpClient,大部分特别简单,有一些看起来比较高级,但是用起来都不怎么好用.调用关系不清楚,结构有点混乱.所以也就萌生了自己封装HttpClient工具类的想法.要做就 ...
- Atitit.http httpclient实践java c# .net php attilax总结
Atitit.http httpclient实践java c# .net php attilax总结 1. Navtree>> net .http1 2. Httpclient理论1 2. ...
- HttpClient, HttpClientHandler, and WebRequestHandler Explained
原文地址 https://blogs.msdn.microsoft.com/henrikn/2012/08/07/httpclient-httpclienthandler-and-webrequest ...
- HttpClient I/O exception (java.net.SocketException) caught when processing request: Connect
转自:http://luan.iteye.com/blog/1820054 I/O exception (java.net.SocketException) caught when processin ...
随机推荐
- win10系统电脑无法识别u盘的解决办法
一些win10系统用户说插入usb设备的时候出现无法识别usb设备的问题,就此问题,接下来是对应的解决方法. win10系统电脑无法识别U盘的应对方法: 右键“计算机”,从弹出的菜单中选择“属性”项: ...
- 洛谷P4778 Counting swaps 数论
正解:数论 解题报告: 传送门! 首先考虑最终的状态是固定的,所以可以知道初始状态的每个数要去哪个地方,就可以考虑给每个数$a$连一条边,指向一个数$b$,表示$a$最后要移至$b$所在的位置 显然每 ...
- Elasticsearch学习笔记(十一)Mapping原理
一.Mapping的功能作用 Mapping是定义如何存储和索引一个document及其所包含字段的过程. Mapping是index和type的元数据,每个type都有自己的一个mapping,决定 ...
- Java学习-052-(mybatis+mysql)访问接口时提示:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
在配置mybatis,访问接口提示: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found),部 ...
- 《图解HTTP》读书笔记(七:通信数据转发程序-代理/网关/隧道)
HTTP通信时,除客户端和服务器以外,还有一些用于通信数据转发的应用程序,例如代理.网关和隧道,它们可以配合服务器工作.这些服务器和应用程序可以将请求转发给通信线路上的下一站服务器,并且能接收从那台服 ...
- 把玩Pencil项目之编译并运行
Pencil是个好项目.使用Electron作为运行环境,如同Vs Code一样,将JS跨平台桌面应用做了一个好的示范.个人很喜欢这种方式,毕竟多年来关注Web全栈开发,有一种JS一统天下的感觉.我的 ...
- MongoDB基本信息
一.MongoDB简介 来源:在2007年,由纽约一个叫10gen的创业团队开发,公司现在叫做MongoDB Inc,最初被开发为PAAS(平台即服务). 数据库类型:基于分布式文件存储的数据库.由C ...
- 解决CentOS(6和7版本),/etc/sysconfig/下没有iptables的问题
一.Centos 6版本解决办法: 1.任意运行一条iptables防火墙规则配置命令: iptables -P OUTPUT ACCEPT 2.对iptables服务进行保存: service ip ...
- 从后台拿到echarts的数据值,求出百分比
从后台拿到数据是一个数组的格式 例: var arr = [6,4,0,0,0,0,0,0]; 后来得到新的需求,需要鼠标移入的时候提示数量和百分比,数量本身就可以拿到, 求百分比的时候:先拿到数组最 ...
- 关于linux系统CPU篇--->CPU使用率升高
1.CPU使用率为单位时间内CPU使用情况的统计,以百分比的方式展示. LINUX作为一个多任务操作系统,将每个CPU的时间划分为很短的时间片,再通过调度器轮流分配给各个任务使用,因此造成多任务同时运 ...