As far as I know, there're two possible patterns to implement a timeout to task-based asynchronous methods:
Built-in timeout
public Task DoStuffAsync(TimeSpan timeout)
This approach is harder to implement because it's not easy to implement a global timeout for the entire call stack. For example, a Web API controller receives an HTTP request and it calls DoStuffAsync
, and the caller wants a global timeout of 3 seconds.
That is, each inner async method call will need to receive the subtract of already used time...
No built-in timeout
public Task DoStuffAsync(CancellationToken cancellationToken)
..........
CancellationTokenSource cancellationSource = new CancellationTokenSource();
Task timeoutTask = Task.Delay(3000);
if(await Task.WhenAny(DoStuffAsync(cancellationTokenSource), timeoutTask) == timeoutTask)
{
cancellationSource.Cancel();
throw new TimeoutException();
}
This seems to be the most reliable and easy to implement pattern. The first caller defines a global timeout, and if it time outs, all pending operations will be cancelled. Also, it provides a cancellation token to the immediate caller and inner calls will share the same cancellation token reference. Thus, if the top caller time outs, it will be able to cancel any working thread.
The whole question
Is there any pattern that I'm missing or, am I in the right way if I develop APIs using the no built-in timeout?
See Question&Answers more detail:os