在 Polly 4.3 的特定条件下停止执行

Stop Execution on certain condition on Polly 4.3

我们开始在遗留 WinForms 项目中使用 Polly 库,该项目仍然在 .NET 4.0 框架上运行(这是必需的)。

问题是我们必须使用 4.3 版的 Polly 库,而且很难找到问题的解决方案,因为我们找到的所有文档都是关于该库的更新版本的。

例如,我们无法将重试回调中的 Context 值传递给执行,因为 Context 是只读的,并且我们无法将参数传递给执行委托,因为它使用 Action类型。

对于所有这些问题,我们都找到了创造性的解决方案,但我们仍然找不到在特定条件下停止执行的方法。

在 Polly 5 中,为此引入了 CancellationToken,但我想在以前的版本中也有强制停止重试的方法。

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);
        }
    });

有什么想法吗?

我认为你试图从错误的角度解决问题。

与其尝试取消重试,不如尝试避免触发重试。

我创建了一个 sample application in dotnetfiddle 以确保我提出的解决方案也适用于 Polly 4.3 版

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();
}

Handle<TException> 方法有 an overload 接受委托 (Func<Exception, bool>)。换句话说,您可以定义一个谓词,您可以在其中定义哪些异常应该触发重试。

根据我的理解,除了抛出 TimeoutException 之外,您希望在每种情况下都执行重试。你可以像这样很容易地指定它:

.Handle<Exception>(ex => !(ex is TimeoutException))