使用 Polly 在异步函数中进行重试尝试

19

我想尝试将一个失败的操作重试3次。

我正在使用Polly进行重试操作。

如果重试操作失败,我希望能够获取异常并再次重试2次,以此类推。

return await Policy
           .Handle<CustomException>()
           .RetryAsync(3, onRetryAsync: async (exception, retryCount, context) =>
           {
               return await runner.run(params);
           });

这个函数应该返回

Task<IReadOnlyCollection<string>>

我遇到了以下错误:

异步lambda表达式转换为返回委托的任务时无法返回值

1个回答

35

我认为在重试策略中运行逻辑是不寻常的 - 除非我误解了你的问题。更典型的做法是通过调用运行逻辑的方法来执行策略。

像这样:

我认为重试策略中直接运行逻辑是不寻常的,通常的做法是通过调用一个运行逻辑的方法来执行策略。

类似于这样:

async Task Main()
{
    var polly = Policy
           .Handle<Exception>()        
           .RetryAsync(3, (exception, retryCount, context) => Console.WriteLine($"try: {retryCount}, Exception: {exception.Message}"));

    var result = await polly.ExecuteAsync(async () => await DoSomething());
    Console.WriteLine(result);
}

int count = 0;

public async Task<string> DoSomething()
{
    if (count < 3)
    {
        count++;
        throw new Exception("boom");
    }

    return await Task.FromResult("foo");
}

输出

try: 1, Exception: boom
try: 2, Exception: boom
try: 3, Exception: boom
foo

我认为你已经很好地理解了我的问题。只是为了确保我理解得正确。 如果抛出异常,DoSomething将再次运行,如果没有抛出异常,则会返回结果但不会再次运行? - Ace
2
正确,result 将包含您的方法返回的任何内容。如果它失败了太多次,它将像通常抛出异常一样。 - Crowcoder
1
我不确定我理解问题#1——如果需要,这种重试策略将最多尝试3次。如果没有抛出它处理的异常,它将不会重试。#2——您不需要将异常传递给DoSomething,因为异常来自那里。您可以只使用普通的try/catch - Crowcoder
1
在重试委托中,您可以设置或调用设置一个变量的方法,该变量可由(在此示例中) DoSomething 访问。您可以根据它编写逻辑。 - Crowcoder
1
Retry策略有多个重载版本,其中onRetry委托会传递Polly.Context。而ExecuteAsync(...)也有多个重载版本,可以将要执行的委托作为输入参数传递Polly.Context。因此,您可以通过将数据存储在Polly.Context字典中来共享数据。请参见https://github.com/App-vNext/Polly/wiki/Keys-And-Context-Data#using-context-for-custom-data;http://www.thepollyproject.org/2017/05/04/putting-the-context-into-polly/。通过`Polly.Context`共享数据避免了共享本地变量的问题;如果策略定义与使用不在同一范围内,则非常有用。 - mountain traveller
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接