I have my web requests handled by this code;
Response = await Client.SendAsync(Message, HttpCompletionOption.ResponseHeadersRead, CToken);
While you can rely on WithCancellation for reuse purposes, a simpler solution for a timeout (which doesn't throw OperationCanceledException) would be to create a timeout task with Task.Delay and wait for the first task to complete using Task.WhenAny:
public static Task WithTimeout(this Task task, TimeSpan timeout)
{
var timeoutTask = Task.Delay(timeout).ContinueWith(_ => default(TResult), TaskContinuationOptions.ExecuteSynchronously);
return Task.WhenAny(task, timeoutTask).Unwrap();
}
Or, if you want to throw an exception in case there's a timeout instead of just returning the default value (i.e. null):
public static async Task WithTimeout(this Task task, TimeSpan timeout)
{
if (task == await Task.WhenAny(task, Task.Delay(timeout)))
{
return await task;
}
throw new TimeoutException();
}
And the usage would be:
var content = await Response.Content.ReadAsStringAsync().WithTimeout(TimeSpan.FromSeconds(1));