Polly RetryForever 不是 Retry



我想检查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

我可能迟到了,但让我分享一下我的智慧。


当你定义一个策略时,你必须预先知道你想要修饰一个syncasync方法/函数。

同步方法的重试策略

Policy
.Handle<Exception>()
.RetryForever();

异步方法的重试策略

Policy
.Handle<Exception>()
.RetryForeverAsync();
  • 在前一种情况下,您有一个可以预测的Execute方法
    • anAction(一个没有返回值的方法)
    • Func<TResult>(具有TResult类型返回值的方法)
    • 和其他一些重载
  • 在后一种情况下,你有一个ExecuteAsync方法可以预测
    • aFunc<Task>(没有返回值的异步方法)
    • Func<Task<TResult>>(具有TResult类型返回值的异步方法)
    • 和其他一些重载

同步功能的重试策略

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不是awaited。

让我们拭目以待

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方法的策略,并且你awaitExecuteAsync,那么它也会工作。为什么?因为ExecuteAsyncawait是提供的委托,即使您没有将委托定义为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;
});

相关内容

  • 没有找到相关文章

最新更新