Inside a Portable Class Library, I've the following method which post data to a specific Url. The method works great. However I'd like to specify a more aggressive timeout (the default is 100 seconds).
Considering that there's no Timeout property on the HttpWebRequest class from the Portable Class Library, how can I make sure that the call is abandoned if it takes longer than a few seconds?
public async Task<HttpResponse> PostAsync(Uri uri, string data)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
using (Stream requestStream = await request.GetRequestStreamAsync())
{
byte[] postBytes = Encoding.UTF8.GetBytes(data);
requestStream.Write(postBytes, 0, postBytes.Length);
}
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
return new HttpResponse(response.StatusCode, await new StreamReader(response.GetResponseStream()).ReadToEndAsync());
}
The default value is 100,000 milliseconds (100 seconds).
The HttpWebRequest class provides support for the properties and methods defined in WebRequest and for additional properties and methods that enable the user to interact directly with servers using HTTP.
Below code either will return a HttpWebResponse or null if timed out.
HttpWebResponse response = await TaskWithTimeout(request.GetResponseAsync(), 100);
if(response != null)
{
....
}
Task<HttpWebResponse> TaskWithTimeout(Task<WebResponse> task, int duration)
{
return Task.Factory.StartNew(() =>
{
bool b = task.Wait(duration);
if (b) return (HttpWebResponse)task.Result;
return null;
});
}
--EDIT--
Creating an extension method would be even better
public static class SOExtensions
{
public static Task<T> WithTimeout<T>(this Task<T> task, int duration)
{
return Task.Factory.StartNew(() =>
{
bool b = task.Wait(duration);
if (b) return task.Result;
return default(T);
});
}
}
Usage would be:
var response = (HttpWebResponse)await request.GetResponseAsync().WithTimeout(1000);
--EDIT 2--
Another way of doing it
public async static Task<T> WithTimeout<T>(this Task<T> task, int duration)
{
var retTask = await Task.WhenAny(task, Task.Delay(duration))
.ConfigureAwait(false);
if (retTask is Task<T>) return task.Result;
return default(T);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With