Reputation: 1274
I'm using this piece of code to append a TimeOut to a request call that I'm making to ensure that we don't encounter a slow internet connection - and that its handled appropriately.
When I DO meet the timeout condition I get an error message that I've been unable to fix within the extended function.
How to go about this task in general?
Code:
public static class SOExtensions
{
public static Task<T> WithTimeout<T>(this Task<T> task, TimeSpan duration)
{
return Task.Factory.StartNew(() =>
{
bool b = task.Wait(duration);
if (b) return task.Result;
return default(T);
});
}
}
Usage:
var response = await HttpWebRequest
.Create(request)
.GetResponseAsync()
.WithTimeout(TimeSpan.FromSeconds(1));
I handle AggregateException
with this (and through a WebException
), but it still generates AggregateException
when the timeout fails.
Upvotes: 0
Views: 850
Reputation: 457187
I recommend using CancellationToken
for timeouts (new CancellationTokenSource(myTimeSpan).Token
), which you can then use within your async
methods (e.g., for HttpClient
, you pass the token to the GetAsync
method). This takes up fewer resources because the HTTP request itself is canceled.
But if you want an "external" timeout, a more natural approach would be this:
public static async Task<T> WithTimeout<T>(this Task<T> task, TimeSpan duration)
{
var timeout = Task.Delay(duration);
var completeTask = await Task.WhenAny(task, timeout);
if (completeTask == timeout)
return default(T);
else
return await task;
}
This will prevent the exceptions from being wrapped into an AggregateException
. It's not as efficient as the CancellationToken
approach, though, which would look like this:
var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(1));
var response = await new HttpClient().GetAsync(uri, timeout.Token);
Note that the CancellationToken
approach will throw OperationCanceledException
instead of returning a default(T)
if there is a timeout.
Upvotes: 2