We started using the Polly library in our legacy WinForms project which still runs on the .NET 4.0 framework (is a requisite).
The problem is that we have to use version 4.3 of the Polly library and it is difficult to find solutions to the problems because all the documentation we find is about more recent versions of the library.
For example we can't pass Context
values from retry callback to execute because Context
is readonly and we can't pass parameters to execute delegate because it use an Action
type.
To all these problems we have find a creative solution but we can't still found a way to stop the execution on certain condition.
In Polly 5, CancellationToken
was introduced for this purpose but I guess there were ways to force the retry to stop in previous versions as well.
public RetryPolicy DevicePolicy => Policy
.Handle<Exception>()
.WaitAndRetry(
MaxRetries,
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
(exception, timeSpan, retryCount, context) =>
{
//If i get the timeout exception i want to stop the execution
if (exception is TimeoutException)
{
//In Polly 5.0 I can set the cancellationToken but with 4.3 there isn't
var cts = context["CancellationTokenSource"] as CancellationTokenSource;
cts.Cancel();
}
else
{
var errHeader = $"device connection error. Attempt {retryCount} of {MaxRetries}";
Log.Warn(errHeader, exception);
}
});
Any Idea?
CodePudding user response:
I think you have tried to solve the problem from the wrong angle.
Rather than trying to cancel a retry, try to avoid triggering the retry.
I've created a sample application in dotnetfiddle to make sure that my proposed solution work with Polly version 4.3 as well
public static void Main()
{
var retry = Policy
.Handle<Exception>(ex => !(ex is TimeoutException))
.WaitAndRetry(2, _ => TimeSpan.FromSeconds(1));
retry.Execute(WrappedMethod);
}
public static int counter = 0;
public static void WrappedMethod()
{
Console.WriteLine("The wrapped method is called");
if(counter == 1)
throw new TimeoutException();
throw new ArgumentException();
}
The Handle<TException>
method has an overload which accepts a delegate (Func<Exception, bool>
). In other words you can define a predicate where you can define which exceptions should trigger a retry.
According to my understanding you want to perform a retry in each and every case except when a TimeoutException
is thrown. You can specify this really easily like this:
.Handle<Exception>(ex => !(ex is TimeoutException))