I was looking for a Task based way to detect a timeout for a task, without having to Wait()
for it.
The timeout should be put on the innermost task in a chain of continuations, while the Exception should get caught only at the outermost level.
My solution, instead of blocking the execution, returns a Task which wraps the original one, allowing the user to catch an exception in case of time out.
So I came up with this code:
public static Task<T> Timeout<T>(Task<T> baseTask, int milliseconds)
{
var timer = Delay(milliseconds);
return Task.Factory.ContinueWhenAny(
new []
{
baseTask,
timer.ContinueWith<T>(x => { throw new TaskTimeOutException(); })
},
x => x.Result
);
}
The function Delay()
is described in the accepted solution at How to put a task to sleep (or delay) in C# 4.0? .
I would like to improve my code, basically I have a few questions:
- Can someone see possible pitfalls?
- Should the timeout cause a cancellation of the original Task?
Thank you.
EDIT
Based on comments I developed this slight improvement:
public static Task<T> Timeout<T>(Task<T> baseTask, int milliseconds)
{
var timer = Delay(milliseconds);
return Task.Factory.ContinueWhenAny(
new []
{
baseTask,
timer
},
x =>
{
if (x.Equals(baseTask)) return baseTask.Result;
throw new TaskTimeOutException();
}
);
}