Occasionally I have a need to retry an operation several times before giving up. My code is like:
int retries = 3; while(true) { try { DoSomething(); break; // success! } catch { if(--retries == 0) throw; else Thread.Sleep(1000); } }
I would like to rewrite this in a general retry function like:
TryThreeTimes(DoSomething);
Is it possible in C#? What would be the code for the TryThreeTimes()
method?
1. Simple for-loop with try-catch. A simple solution to implement retry logic in Java is to write your code inside a for loop that executes the specified number of times (the maximum retry value).
Retry logic is implemented whenever there is a failing operation. Implement retry logic only where the full context of a failing operation. It's important to log all connectivity failures that cause a retry so that underlying problems with the application, services, or resources can be identified.
Manage operations that continually fail: Although a retry strategy will define the maximum number of times that an operation should be retried, it does not prevent the application repeating the operation again, with the same number of retries.
Blanket catch statements that simply retry the same call can be dangerous if used as a general exception handling mechanism. Having said that, here's a lambda-based retry wrapper that you can use with any method. I chose to factor the number of retries and the retry timeout out as parameters for a bit more flexibility:
public static class Retry { public static void Do( Action action, TimeSpan retryInterval, int maxAttemptCount = 3) { Do<object>(() => { action(); return null; }, retryInterval, maxAttemptCount); } public static T Do<T>( Func<T> action, TimeSpan retryInterval, int maxAttemptCount = 3) { var exceptions = new List<Exception>(); for (int attempted = 0; attempted < maxAttemptCount; attempted++) { try { if (attempted > 0) { Thread.Sleep(retryInterval); } return action(); } catch (Exception ex) { exceptions.Add(ex); } } throw new AggregateException(exceptions); } }
You can now use this utility method to perform retry logic:
Retry.Do(() => SomeFunctionThatCanFail(), TimeSpan.FromSeconds(1));
or:
Retry.Do(SomeFunctionThatCanFail, TimeSpan.FromSeconds(1));
or:
int result = Retry.Do(SomeFunctionWhichReturnsInt, TimeSpan.FromSeconds(1), 4);
Or you could even make an async
overload.
You should try Polly. It's a .NET library written by me that allows developers to express transient exception handling policies such as Retry, Retry Forever, Wait and Retry or Circuit Breaker in a fluent manner.
Policy .Handle<SqlException>(ex => ex.Number == 1205) .Or<ArgumentException>(ex => ex.ParamName == "example") .WaitAndRetry(3, retryAttempt => TimeSpan.FromSeconds(3)) .Execute(() => DoSomething());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With