Reputation: 151
I'm, trying to check a simple RetryForever
of Polly
class Program
{
public static void Main()
{
int i = 0;
var _retryPolicy = Policy
.Handle<Exception>()
.RetryForever();
_retryPolicy.Execute(async () =>
{
Console.WriteLine(i);
i++;
int.Parse("something");
});
Console.ReadLine();
}
}
A you can see I've created a variable i
to track the number of the executions
Excepted Result:
print i
= 0, 1, 2 etc
Actual Result: print i = 0
Upvotes: 2
Views: 701
Reputation: 22819
I might be late to the party but let me share my wisdom.
When you define a policy then you have to know upfront that you want to decorate a sync or an async method/function.
Policy
.Handle<Exception>()
.RetryForever();
Policy
.Handle<Exception>()
.RetryForeverAsync();
Execute
method which could anticipate
Action
(a method without return value)Func<TResult>
(a method with TResult
typed return value)ExecuteAsync
method which could anticipate
Func<Task>
(an async method without return value)Func<Task<TResult>>
(an async method with TResult
typed return value)Policy<int>
.Handle<Exception>()
.RetryForever();
Policy<int>
.Handle<Exception>()
.RetryForeverAsync();
In these cases your to be decorated code should return an int
.
So the Execute
anticipates a Func<int>
delegate
policy.Execute(() => { ... return 42; });
and the ExecuteAsync
anticipates a Func<Task<int>>
delegate
await policy.Execute(async () => { ... return Task.FromResult(42); });
Back to your code
Since you did not made any constraint on the return type during the policy definition that's why you could pass a Func
which returns a Task
(Execute(async () => { ...});
).
So, your Execute
returns a Task
which is not await
ed.
await _retryPolicy.Execute(async () =>
{
Console.WriteLine(i);
i++;
int.Parse("something");
});
If you await
the returned Task
then it will throw a FormatException
.
But that Exception is thrown by the await
which is outside of the Execute
's delegate. So, it will NOT trigger a retry.
_retryPolicy.Execute(() =>
{
Console.WriteLine(i);
i++;
int.Parse("something");
});
By removing async
, your delegate will be an Action
which will throw the FormatException
which could trigger the retry policy.
var _retryPolicy = Policy<int>
.Handle<Exception>()
.RetryForeverAsync();
await _retryPolicy.ExecuteAsync(async () =>
{
Console.WriteLine(i);
i++;
int.Parse("something");
});
If you define your policy for async method and you await
the ExecuteAsync
then it will work as well. Why? Because ExecuteAsync
await
s the provided delegate even if you did not define the delegate as async
await _retryPolicy.ExecuteAsync(() =>
{
Console.WriteLine(i);
i++;
int.Parse("something");
return Task.CompletedTask; //This code is never reached
});
Upvotes: 3
Reputation: 119
I've checked your code and you had right, its stops on 0.
But when i removed async keyword (u didnt have any async operation here) the code runs correct.
So, try this:
using Polly;
int i = 0;
var _retryPolicy = Policy
.Handle<Exception>()
.RetryForever();
_retryPolicy.Execute(() =>
{
Console.WriteLine(i);
i++;
int.Parse("something");
return Task.CompletedTask;
});
Upvotes: 2