/// <summary>This will apply a timeout delay to the task, allowing us to exit early</summary> /// <param name="taskToComplete">The task we will timeout after timeSpan</param> /// <param name="timeSpan">Amount of time to wait before timing out</param> /// <exception cref="TimeoutException">If we time out we will get this exception</exception> /// <returns>The value of the completed task</returns> public static async Task <T> WithTimeout <T>(this Task <T> taskToComplete, TimeSpan timeSpan) { if (taskToComplete.IsCompleted) { return(await taskToComplete); } var timeoutCancellationTokenSource = new CancellationTokenSource(); #if NET40 var completedTask = await TaskEx.WhenAny(taskToComplete, TaskEx.Delay(timeSpan, timeoutCancellationTokenSource.Token)); #else var completedTask = await Task.WhenAny(taskToComplete, Task.Delay(timeSpan, timeoutCancellationTokenSource.Token)); #endif // We got done before the timeout, or were able to complete before this code ran, return the result if (taskToComplete == completedTask) { timeoutCancellationTokenSource.Cancel(); // Await this so as to propagate the exception correctly return(await taskToComplete); } // We did not complete before the timeout, we fire and forget to ensure we observe any exceptions that may occur taskToComplete.Ignore(); throw new TimeoutException(String.Format("WithTimeout has timed out after {0}.", timeSpan)); }
public static async Task <T> WithCancellation <T>(this Task <T> task, CancellationToken cancellationToken) { var tcs = new TaskCompletionSource <bool>(); using (cancellationToken.Register(s => ((TaskCompletionSource <bool>)s).TrySetResult(true), tcs)) { if (task != await TaskEx.WhenAny(task, tcs.Task)) { throw new OperationCanceledException(cancellationToken); } } return(await task); }
public static async Task <T> TimeoutAfter <T>(this Task <T> task, TimeSpan delay) { if (Debugger.IsAttached) { delay = delay.Multiply(10); } await TaskEx.WhenAny(task, TaskEx.Delay(delay)); if (!task.IsCompleted) { throw new TimeoutException("Timeout processing task."); } return(await task); }
/// <summary> /// Executes a provided <see cref="Task"/>, cancelling the task and executing a fallback action if the Task doesn't complete before the provided timeout. /// </summary> /// <param name="ct"></param> /// <param name="taskSelector"></param> /// <param name="timeout"></param> /// <returns></returns> public static async Task Timeout(CancellationToken ct, Func <CancellationToken, Task> taskSelector, TimeSpan timeout, Action onTimedOut) { // We're not using CancellationTokenSource's timeout support because we want to be able to trace code and know when it's // about to be cancelled because of a timeout. using (var tokenSource = new CancellationTokenSource()) { var task = taskSelector(tokenSource.Token); if ((await StaticTask.WhenAny(task, StaticTask.Delay(timeout, ct))) != task) { // We timed out, cancel the task and throw a relevant exception. tokenSource.Cancel(); onTimedOut(); } } }
public static Task <Task> WhenAny([NotNull, ItemNotNull] this IEnumerable <Task> tasks) => TaskEx.WhenAny(tasks);
public static Task <Task <TResult> > WhenAny <TResult>(params Task <TResult>[] tasks) { return(TaskEx.WhenAny <TResult>((IEnumerable <Task <TResult> >)tasks)); }
public static Task <Task> WhenAny(params Task[] tasks) { return(TaskEx.WhenAny((IEnumerable <Task>)tasks)); }