正确实现异步重试方法 [英] Proper implementation of async retry method

查看:178
本文介绍了正确实现异步重试方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请告诉我,这种方法是否正确实现了异步模型?

Please tell me, is the asynchronous model correctly implemented in this method?

我需要实现一种方法,期望该条件得到满足,并且可能会超时.

I need to implement a method that expects the condition to be met, with the possibility of a timeout.

仅供参考:无需制定通用方法

FYI: there is no need to make a generic method

        var timeout = timeout == default ? TimeSpan.FromSeconds(30) : timeout;
        var stopwatch = new Stopwatch();
        stopwatch.Start();
        var delayTimeout = 0;
        do
        {
            delayTimeout += 1000;
            var report = await MethodAsync();
            if (report.Active == true)
            {
                return report;
            }
            await Task.Delay(delayTimeout);
        }
        while (stopwatch.Elapsed < timeout);

        throw new TimeoutException($"Timeout.");

推荐答案

重试方法可以受益于 CancellationToken 参数,因此可以随时取消.同样,如果满足超时条件,则最后一个 Task.Delay 也应省略.无需无故地将 TimeoutException 的抛出延迟额外的几秒钟.

The retry method could benefit from a CancellationToken argument, so that is can be canceled at any moment. Also the last Task.Delay should be omitted in case the timeout condition has been met. No need to delay the throwing of the TimeoutException for some extra seconds without reason.

private async Task<Report> MethodWithRetryAsync(TimeSpan timeout = default,
    CancellationToken cancellationToken = default)
{
    timeout = timeout == default ? TimeSpan.FromSeconds(30) : timeout;
    var stopwatch = Stopwatch.StartNew();
    int delayTimeout = 0;
    while (true)
    {
        var report = await MethodAsync();
        if (report.Active == true) return report;
        delayTimeout += 1000;
        if (stopwatch.Elapsed + TimeSpan.FromMilliseconds(delayTimeout) > timeout)
        {
            throw new TimeoutException();
        }
        await Task.Delay(delayTimeout, cancellationToken);
    }
}

另一个问题是,在等待 MethodAsync 的过程中发生异常时,该异常将立即传播,并且不会尝试重试.视情况而定,这是否可取.

Another issue is that in case of an exception in the awaiting of MethodAsync, the exception will be propagated instantly and no retry will be attempted. This may be desirable or not, depending on the case at hand.

您还可以在方法中添加可选参数 maxRetries ,以允许调用方限制重试次数.同样,对 initialDelay delayIncreament 进行参数化将使该方法更加灵活,以使API更加冗长为代价.

You could also add an optional argument maxRetries to the method, to allow the caller to limit the number of retries. Also parameterizing the initialDelay and the delayIncreament would make the method more flexible, at the cost of making the API more verbose.

这篇关于正确实现异步重试方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆