using System.Threading.Tasks;
public static async Task Main()
var timeout = Policy.TimeoutAsync(
var ts = TimeSpan.FromSeconds(Math.Pow(2, ctx.GetAttemptNumber() + 1));
Console.WriteLine($"New timeout: {ts}");
onTimeoutAsync: (ctx, ts, t) => { Console.WriteLine($"Timeout: {ts}"); return Task.CompletedTask; });
.Handle<TimeoutRejectedException>()
sleepDurationProvider: _ => TimeSpan.FromMilliseconds(100),
onRetry: (ex, ts, attemptCount, ctx) =>
Console.WriteLine($"Retry after {attemptCount}th attempt");
ctx.SetAttemptNumber(attemptCount);
var strategy = Policy.WrapAsync(retry, timeout);
await strategy.ExecuteAsync(async (ctx, ct) => {
Console.WriteLine($"-=< {ctx.GetAttemptNumber()}th attempt >=-");
Console.WriteLine($"Execution started: {DateTime.UtcNow}");
await Task.Delay(100_000, ct);
}, ctx, CancellationToken.None);
public static class ContextExtensions
private static readonly string key = "AttemptNumber";
public static Context SetAttemptNumber(this Context context, int attemptNumber)
context[key] = attemptNumber;
public static int GetAttemptNumber(this Context context)
context.TryGetValue(key, out object obj);
return obj is int attemptNumber ? attemptNumber : 0;