示例#1
0
 /// <summary>
 /// Repeatedly executes the specified asynchronous task while it satisfies the current retry policy.
 /// </summary>
 /// <param name="taskFunc">A function that returns a started task (also known as "hot" task).</param>
 /// <param name="cancellationToken">The token used to cancel the retry operation. This token does not cancel the execution of the asynchronous task.</param>
 /// <returns>
 /// Returns a task that will run to completion if the original task completes successfully (either the
 /// first time or after retrying transient failures). If the task fails with a non-transient error or
 /// the retry limit is reached, the returned task will transition to a faulted state and the exception must be observed.
 /// </returns>
 public Task <TResult> ExecuteAsync <TResult>(Func <Task <TResult> > taskFunc, CancellationToken cancellationToken)
 {
     if (taskFunc == null)
     {
         throw new ArgumentNullException(nameof(taskFunc));
     }
     return(new AsyncExecution <TResult>(taskFunc, RetryStrategy.GetShouldRetry(), new Func <Exception, bool>(ErrorDetectionStrategy.IsTransient), new Action <int, Exception, TimeSpan>(OnRetrying), RetryStrategy.FastFirstRetry, cancellationToken).ExecuteAsync());
 }
示例#2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RetryPolicy" /> class with the specified number of retry attempts and parameters defining the progressive delay between retries.
 /// </summary>
 /// <param name="errorDetectionStrategy">The <see cref="ITransientErrorDetectionStrategy" /> that is responsible for detecting transient conditions.</param>
 /// <param name="retryStrategy">The strategy to use for this retry policy.</param>
 public RetryPolicy(ITransientErrorDetectionStrategy errorDetectionStrategy, RetryStrategy retryStrategy)
 {
     Guard.ArgumentNotNull(errorDetectionStrategy, "errorDetectionStrategy");
     Guard.ArgumentNotNull(retryStrategy, "retryPolicy");
     ErrorDetectionStrategy = errorDetectionStrategy;
     if (errorDetectionStrategy == null)
     {
         throw new InvalidOperationException("The error detection strategy type must implement the ITransientErrorDetectionStrategy interface.");
     }
     RetryStrategy = retryStrategy;
 }
示例#3
0
 /// <summary>
 /// Repetitively executes the specified asynchronous task while it satisfies the current retry policy.
 /// </summary>
 /// <param name="taskAction">A function that returns a started task (also known as "hot" task).</param>
 /// <param name="cancellationToken">The token used to cancel the retry operation. This token does not cancel the execution
 /// of the asynchronous task.</param>
 /// <returns>
 /// Returns a task that will run to completion if the original task completes successfully (either the
 /// first time or after retrying transient failures). If the task fails with a non-transient error or
 /// the retry limit is reached, the returned task will transition to a faulted state and the exception must be observed.
 /// </returns>
 public Task RunWithRetryAsync(Func <Task> taskAction, CancellationToken cancellationToken = default)
 {
     return(taskAction == null
         ? throw new ArgumentNullException(nameof(taskAction))
         : RunWithRetryAsync(
                taskAction,
                RetryStrategy.GetShouldRetry(),
                new Func <Exception, bool>(ErrorDetectionStrategy.IsTransient),
                new Action <int, Exception, TimeSpan>(OnRetrying),
                RetryStrategy.FastFirstRetry,
                cancellationToken));
 }
示例#4
0
        /// <summary>
        /// Repetitively executes the specified action while it satisfies the current retry policy.
        /// </summary>
        /// <typeparam name="TResult">The type of result expected from the executable action.</typeparam>
        /// <param name="func">A delegate that represents the executable action that returns the result of type <typeparamref name="TResult" />.</param>
        /// <returns>The result from the action.</returns>
        public virtual TResult ExecuteAction <TResult>(Func <TResult> func)
        {
            Guard.ArgumentNotNull(func, "func");
            int         num         = 0;
            ShouldRetry shouldRetry = RetryStrategy.GetShouldRetry();
            TResult     result;

            while (true)
            {
                Exception ex;
                TimeSpan  zero;
                try
                {
                    result = func();
                    break;
                }
                catch (RetryLimitExceededException ex2)
                {
                    if (ex2.InnerException != null)
                    {
                        throw ex2.InnerException;
                    }
                    result = default;
                    break;
                }
                catch (Exception ex3)
                {
                    ex = ex3;
                    if (!ErrorDetectionStrategy.IsTransient(ex) || !shouldRetry(num++, ex, out zero))
                    {
                        throw;
                    }
                }
                if (zero.TotalMilliseconds < 0.0)
                {
                    zero = TimeSpan.Zero;
                }
                OnRetrying(num, ex, zero);
                if (num > 1 || !RetryStrategy.FastFirstRetry)
                {
                    Task.Delay(zero).Wait();
                }
            }
            return(result);
        }