Request timeouts vs. connect timeouts in ExecuteAsync

3,855 views
Skip to first unread message

Stephan Steiner

unread,
Sep 27, 2012, 3:57:24 AM9/27/12
to rest...@googlegroups.com
Hi

Is it me or am I correct in assuming that in ExecuteAsync, we're only dealing with connect timeouts, but not request timeouts? When I set request.Timeout to 10000, then call ExecuteAsync if the server isn't there, after 10 seconds I get a response with status TimeOut. If however the server is there at the point of making the request, but then I pause it (just press pause in the debugger), the request keeps on going and going and going. I'd expect it to return with status TimeOut after 10 seconds - or have another time that can be configured somewhere that controls the wait time for an ongoing request (like you can do with WCF for instance).

Am I missing something?

Thanks
Stephan

Ursin Brunner

unread,
Jan 9, 2013, 6:51:28 PM1/9/13
to rest...@googlegroups.com
Hi Stephan

Did you ever find a solution for this problem? I'm currently working on monodroid and have the same probleme, my request.timeout never worked. On iOS, exactly the same code, the Timeout works perfekt.
Thanks for any hints.

Regards
Ursin

Stephan Steiner

unread,
Mar 28, 2013, 8:32:12 AM3/28/13
to rest...@googlegroups.com
Hi Ursin

Unfortunately no (and sorry for not responding to the direct mail... somehow it slipped through the cracks). Have you made any progress on this? ATM I even have the same issue on Windows. I'm using RestSharp for a long poll scenario and for some reason the remote end in a rare and unreproducible scenario "forgets" about the mobile client, and since the request never times out on the mobile client, the client gets no status updates anymore.

If only we had asynch/await on Xamarin, I'd use the synchronous API. Now I'm afraid I have to descend into the depths of the source to try and find something that goes wrong.

Regards
Stephan

Stephan Steiner

unread,
Mar 28, 2013, 9:22:04 AM3/28/13
to rest...@googlegroups.com
Ahh... debug and you shall find :)

This discussion gave me the hint I needed for the fix. Get request should already work, but for anything that requires sending data first, you need to modify Http.Async.cs as follows:

In private void RequestStreamCallback(IAsyncResult result, Action<HttpResponse> callback)

The last line is

webRequest.BeginGetResponse(r => ResponseCallback(r, callback), webRequest);

And therein lies the problem. As the MSDN Article shows, you need to start the timeout mechanism after calling BeginGetResponse. And that is never done for POST/PUT/..

So, I replaced the line with

            IAsyncResult asyncResult = webRequest.BeginGetResponse(r => ResponseCallback(r, callback), webRequest);
            SetTimeout(asyncResult, _timeoutState);


The way the code on git is written, it works for GET (from private HttpWebRequest GetStyleMethodInternalAsync(string method, Action<HttpResponse> callback)

....
var asyncResult = webRequest.BeginGetResponse(result => ResponseCallback(result, callback), webRequest);
SetTimeout(asyncResult, _timeoutState);
...

but in private void WriteRequestBodyAsync(HttpWebRequest webRequest, Action<HttpResponse> callback),

if (HasBody || HasFiles)

asyncResult = webRequest.BeginGetRequestStream(result => RequestStreamCallback(result, callback), webRequest);
..
SetTimeout(asyncResult, _timeoutState);

If the request has no body or files, then

asyncResult = webRequest.BeginGetResponse(r => ResponseCallback(r, callback), webRequest);

So SetTimeout is set on the proper asynchResult. But with a body/files, the timeout was only set for getting the request stream... so if the server is not around, you'd get the timeout, but if you get the request stream to write to, you can write, and the if the server doesn't respond within the required time, you don't get the timeout.

I'm now off to test if this works on M4A or if I need to write my own timeout mechanism for that.


Hope it helps.

Cheers
Stephan
Reply all
Reply to author
Forward
0 new messages