Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
using System;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using log4net;
namespace Utils
public static class RetryHelper
//I am using log4net but swap in your favourite
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static async Task RetryOnExceptionAsync(
int times, TimeSpan delay, Func<Task> operation)
await RetryOnExceptionAsync<Exception>(times, delay, operation);
public static async Task RetryOnExceptionAsync<TException>(
int times, TimeSpan delay, Func<Task> operation) where TException : Exception
if (times <= 0)
throw new ArgumentOutOfRangeException(nameof(times));
var attempts = 0;
await operation();
catch (TException ex)
if (attempts == times)
await CreateDelayForException(times, attempts, delay, ex);
} while (true);
private static Task CreateDelayForException(
int times, int attempts, TimeSpan delay, Exception ex)
var delay = IncreasingDelayInSeconds(attempts);
Log.Warn($"Exception on attempt {attempts} of {times}. " +
"Will retry after sleeping for {delay}.", ex);
return Task.Delay(delay);
internal static int[] DelayPerAttemptInSeconds =
(int) TimeSpan.FromSeconds(2).TotalSeconds,
(int) TimeSpan.FromSeconds(30).TotalSeconds,
(int) TimeSpan.FromMinutes(2).TotalSeconds,
(int) TimeSpan.FromMinutes(10).TotalSeconds,
(int) TimeSpan.FromMinutes(30).TotalSeconds
static int IncreasingDelayInSeconds(int failedAttempts)
if (failedAttempts <= 0) throw new ArgumentOutOfRangeException();
return failedAttempts > DelayPerAttemptInSeconds.Length ? DelayPerAttemptInSeconds.Last() : DelayPerAttemptInSeconds[failedAttempts];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment