You technically can't take a task and force it to be canceled after some period of time. The best that you can do is create a new task that will be marked as canceled after the given period of time, or will be completed when the other task is if it finishes in time.
A key point to note is that the operation timing out doesn't stop the task from continuing on with it's work, it just fires off all continuations of this new task "early" if the timeout is reached.
Doing this is pretty trivial, thanks to the use of CancellationToken
:
var newTask = task.ContinueWith(t => { }
, new CancellationTokenSource(timeoutTime).Token);
We can combine this patter with WhenAny
to easily ensure that any exceptions are properly propagated through to the continuation. A copy for tasks with/without a result is also needed:
public static Task WithTimeout(Task task, TimeSpan timeout)
{
var delay = task.ContinueWith(t => { }
, new CancellationTokenSource(timeout).Token);
return Task.WhenAny(task, delay).Unwrap();
}
public static Task<T> WithTimeout<T>(Task<T> task, TimeSpan timeout)
{
var delay = task.ContinueWith(t => t.Result
, new CancellationTokenSource(timeout).Token);
return Task.WhenAny(task, delay).Unwrap();
}