How to cancel an async WebApi action after timeout?
-
27-06-2021 - |
Pergunta
Using ASP.Net WebAPI, I have a controller with an asynchronous action similar to the following:
[HttpPost]
public async Task<string> DoSomething(string foo)
{
var result = await MyAsynchronousTask(foo);
return result;
}
What this controller does is unimportant. Whats important is that it is awaiting an asynchronous task using the new .net 4.5 async/await support.
Question: How do I tell it to time out after a specified duration? I don't necessarily want to cancel the task, I just want to prevent the caller from hanging on forever. (Although, I would be interested in seeing it both ways.)
Solução
I made a version in LINQPad with the 'C# Program' selection - it compiles and runs with output of 2 lines, showing both the time-out and success cases:
Timeout of 00:00:05 expired
Successfully got result of foo
Here's the snippet:
void Main()
{
CallGetStringWithTimeout(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10)).Wait();
CallGetStringWithTimeout(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(0)).Wait();
}
public async Task CallGetStringWithTimeout(TimeSpan callTimeout, TimeSpan callAddedDelay)
{
var myTask = GetStringAsync(callAddedDelay);
await Task.WhenAny(Task.Delay(callTimeout), myTask);
if (myTask.Status == TaskStatus.RanToCompletion)
{
Console.WriteLine ("Successfully got result of {0}", await myTask);
}
else
{
Console.WriteLine ("Timeout of {0} expired", callTimeout);
}
}
public async Task<string> GetStringAsync(TimeSpan addedDelay)
{
await Task.Delay(addedDelay);
return "foo";
}
However, the 'normal' way is using CancellationTokenSource and specifying your timeout as the ctor param. If you already have a CancellationTokenSource, you can call the CancelAfter method on it, which will schedule the cancellation for the specified timeout.