我想检查Polly的简单RetryForever
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();
}
}
您可以看到,我创建了一个变量i
来跟踪执行的次数
除外结果:printi
= 0, 1, 2等
实际结果:打印I = 0
我可能迟到了,但让我分享一下我的智慧。
当你定义一个策略时,你必须预先知道你想要修饰一个sync或async方法/函数。
同步方法的重试策略
Policy
.Handle<Exception>()
.RetryForever();
异步方法的重试策略
Policy
.Handle<Exception>()
.RetryForeverAsync();
- 在前一种情况下,您有一个可以预测的
Execute
方法- an
Action
(一个没有返回值的方法) - 或
Func<TResult>
(具有TResult
类型返回值的方法) - 和其他一些重载
- an
- 在后一种情况下,你有一个
ExecuteAsync
方法可以预测- a
Func<Task>
(没有返回值的异步方法) - 或
Func<Task<TResult>>
(具有TResult
类型返回值的异步方法) - 和其他一些重载
- a
同步功能的重试策略
Policy<int>
.Handle<Exception>()
.RetryForever();
异步函数的重试策略
Policy<int>
.Handle<Exception>()
.RetryForeverAsync();
在这些情况下,你要装饰的代码应该返回一个int
。
所以Execute
预期Func<int>
委托
policy.Execute(() => { ... return 42; });
和ExecuteAsync
预期Func<Task<int>>
委托
await policy.Execute(async () => { ... return Task.FromResult(42); });
回到你的代码
由于在策略定义期间您没有对返回类型进行任何约束,这就是为什么您可以传递返回Task
(Execute(async () => { ...});
)的Func
。
因此,您的Execute
返回的Task
不是await
ed。
让我们拭目以待
await _retryPolicy.Execute(async () =>
{
Console.WriteLine(i);
i++;
int.Parse("something");
});
如果你await
返回的Task
,那么它将抛出一个FormatException
。但是这个异常是由await
抛出的,它在Execute
的委托之外。因此,它将NOT触发重试
修复选项A
_retryPolicy.Execute(() =>
{
Console.WriteLine(i);
i++;
int.Parse("something");
});
通过删除async
,你的委托将是一个Action
,它将抛出FormatException
,这可能触发重试策略。
修复选项B
var _retryPolicy = Policy<int>
.Handle<Exception>()
.RetryForeverAsync();
await _retryPolicy.ExecuteAsync(async () =>
{
Console.WriteLine(i);
i++;
int.Parse("something");
});
如果你定义async方法的策略,并且你await
ExecuteAsync
,那么它也会工作。为什么?因为ExecuteAsync
await
是提供的委托,即使您没有将委托定义为async
await _retryPolicy.ExecuteAsync(() =>
{
Console.WriteLine(i);
i++;
int.Parse("something");
return Task.CompletedTask; //This code is never reached
});
我检查了你的代码,你是对的,它停在0。
但是当我删除async关键字(你没有任何async操作在这里)代码运行正确。
那么,试试这个:
using Polly;
int i = 0;
var _retryPolicy = Policy
.Handle<Exception>()
.RetryForever();
_retryPolicy.Execute(() =>
{
Console.WriteLine(i);
i++;
int.Parse("something");
return Task.CompletedTask;
});