13

So there are two timeout properties that can be set on HttpClient: HttpClient.TimeOut and WebRequestHandler.ReadWriteTimeout.

The first one is just a timeout for the whole request/response, so if a download/upload takes longer than that, I am out of luck and get cut off in the middle of transfer, no questions asked. This can obviously be overridden by setting the timeout to Infinite, but I am not certain what consequences does that have.

Now the latter (ReadWriteTimeOut) - at least to my understanding - should be propagated all the way down to NetworkStream, where it affects how long a request/response stream can block (be idle) until timeout.

The HttpClient is using asynchronous versions of the HttpWebRequest methods, but as stated here:

In the case of asynchronous requests, it is the responsibility of the client application to implement its own time-out mechanism.

It is not explained at all which time-out mechanism they have in mind (network stream idle timeout? timeout for the whole HTTP GET? etc...), so that makes me greatly confused.

So my question is, how exactly does HttpClient handle network/protocol timeouts? I want to use HttpClient to upload/download potentially large files, so for that I set the HttpClient.TimeOut to infinite. But I am worried that by doing so, the app is at risk of waiting infinitely for some event that the server/network refuses to complete.

8
  • Did you get more details about these time-outs? Commented Nov 4, 2015 at 7:38
  • @SandeepKumar Besides my comments on the "Leo Y"s answer below, I did not really get any more details. There are too many layers to decompile and go through for me. I suggest to use trial-and-error to test the timeout cases you are interested in.
    – Paya
    Commented Nov 5, 2015 at 16:38
  • Ok. One more thing, how you get WebRequestHandler.ReadWriteTimeout using httpClient object? Commented Nov 6, 2015 at 3:11
  • 1
    @SandeepKumar Pass an instance of WebRequestHandler to the constructor of HttpClient. Before you do that, set the ReadWriteTimeout property of WebRequestHandler to whatever you want. This article might help explain some things.
    – Paya
    Commented Nov 7, 2015 at 12:53
  • 1
    @AntonyThomas Are you aware I have linked to that very article in my comment from Nov 7 '15? It's just there, 2 comments above from yours.
    – Paya
    Commented Sep 29, 2016 at 21:53

2 Answers 2

1

There are 2 options when you download a file using HttpClient

  1. Use HttpCompletionOption.ResponseContentRead on your Get request (that's a default implicit option). Then HttpClient.Timeout is effectively applied to the entire download procedure. I suppose that's the case when you thought about Infinite timeout

  2. Explicitly use HttpCompletionOption.ResponseHeadersRead on your Get request. Then HttpClient.Timeout is applied only to getting Head response without content. After that you could download the content managing timeout at your own, e.g. by response.Content.ReadAsStreamAsync()

I suppose the option 2 is what you were seeking of. Just setup a HttpClient.Timeout to get response from server in reasonable time and then download content

0

Your citation is for HttpWebRequest. However, HttpClient.Timeout (working only in .NET 4.5) is for HttpClient. So, it handles timing out when HttpClient API is used. However, set it to infinite is a bad practice. In that case, internal timeouts are in use which will result in throwing exception after ~10 minutes (if internal timeout values weren't changed in .NET 4.5)

7
  • As I said, HttpClient is just a wrapper around HttpWebRequest so the citation is relevant. Can you elaborate more on those 'internal timeouts'? I find your statement quite opaque since my original question is literally about details of the internals. Also, after setting .Timeout to infinite, I was easily able to keep the connection open for much longer than even 20 minutes.
    – Paya
    Commented Apr 25, 2015 at 9:41
  • HttpClient isn't a wrapper since it's URL independent in opposite to HttpWebRequest which is bound to specific URL. You can keep a connection open if you implement a specific behavior on the server-side. For example SSE (server-sent events) protocol makes use of it. A single call issuing (e.g. calling HttpClient.GetStringAsync()) makes use of the HttpWebRequest async methods for implementation, as you mentioned. I'll check the exact use of HttpClient.Timeout and will update the answer with this information.
    – Leo Y
    Commented Apr 25, 2015 at 10:29
  • 1
    It is a wrapper because it just delegates all HTTP protocol handling down to HttpWebRequest. The fact that you can use it for multiple URLs is irrelevant. HttpClient.Timeout is pretty much useless because it just works by setting up a timer at the beginning of a request, and if the entire async operation (request + response) is not finished in time, it just gets cancelled. Something anyone can implement with CancellationTokenSource + Task.Delay at the most abstract layer, so it's useless property. The question is about the internal timeouts as you mentioned.
    – Paya
    Commented Apr 25, 2015 at 10:36
  • In the matter of fact it is used as timeout for cancellation token. Now, having said all above, you've got the answer to your question about "How HttpClient handles timeout".
    – Leo Y
    Commented Apr 25, 2015 at 10:55
  • No I do not: So my question is, how exactly does HttpClient handle network/protocol timeouts?. I am yet to learn how the interaction of HttpClient, HttpWebRequest, NetworkStream and all the other layers contribute to the final timeout mechamisms in the HttpClient. For example, does setting HttpClient.Timeout to infinite mean that HttpClient will never timeout? If not, then under what exact circumstances will the HttpClient timeout?
    – Paya
    Commented Apr 25, 2015 at 11:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.