Created
March 22, 2012 19:00
-
-
Save eulerfx/2161819 to your computer and use it in GitHub Desktop.
TPL retry logic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Utility methods for <see cref="System.Threading.Tasks.Task"/>. | |
/// </summary> | |
public static class TaskHelper | |
{ | |
/// <summary> | |
/// Returns a task which retries the task returned by the specified task provider. | |
/// </summary> | |
/// <typeparam name="TResult"></typeparam> | |
/// <param name="taskProvider">The task returning function.</param> | |
/// <param name="maxAttemps">The maximum number of retries.</param> | |
/// <param name="shouldRetry">A predicate function which determines whether an exception should cause a retry. The default returns true for all exceptions.</param> | |
/// <returns></returns> | |
/// <exception cref="System.ArgumentNullException"></exception> | |
/// <exception cref="System.ArgumentOutOfRangeException"></exception> | |
public static Task<TResult> Retry<TResult>(Func<Task<TResult>> taskProvider, int maxAttemps, Func<Exception, bool> shouldRetry = null) | |
{ | |
Require.NotNull(taskProvider); | |
Require.Positive(maxAttemps, "maxAttemps"); | |
if (shouldRetry == null) | |
shouldRetry = ex => true; | |
return taskProvider() | |
.ContinueWith(task => RetryContinuation(task, taskProvider, maxAttemps, shouldRetry)); | |
} | |
/// <summary> | |
/// A task continuation which attempts a retry if a task is faulted. | |
/// </summary> | |
/// <typeparam name="TResult"></typeparam> | |
/// <param name="task"></param> | |
/// <param name="taskProvider"></param> | |
/// <param name="attemptsRemaining"></param> | |
/// <param name="shouldRetry"></param> | |
/// <returns></returns> | |
static TResult RetryContinuation<TResult>(Task<TResult> task, Func<Task<TResult>> taskProvider, int attemptsRemaining, Func<Exception, bool> shouldRetry) | |
{ | |
if (task.IsFaulted) | |
{ | |
if (attemptsRemaining > 0 && shouldRetry(task.Exception.InnerException)) | |
{ | |
return taskProvider() | |
.ContinueWith(retryTask => RetryContinuation(retryTask, taskProvider, --attemptsRemaining, shouldRetry)) | |
.Result; | |
} | |
else | |
{ | |
// will throw AggregateException | |
return task.Result; | |
} | |
} | |
else | |
{ | |
return task.Result; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment