为什么在使用Polly的后续重试期间HttpClient会继续失败?

Equ*_*lsk 4 c# asynchronous task-parallel-library polly

我有几种方法需要某种互联网连接.如果连接失败,我想在失败前重试该方法一段时间.由于应用程序可以在等待成功响应时愉快地继续运行,因此我希望异步执行此操作.

我正在使用Polly(5.3.1)来实现异步重试逻辑杠杆Tasks.

我正在通过禁用Wi-Fi启动该过程并在重试窗口期间启用它来模拟断开连接.我希望在再次启用我的连接之后,该方法在重试时会成功,我所看到的是该方法继续抛出一个HttpRequestException好像连接已关闭,直到重试完成,此时它将抛出给调用者.
如果我正常启用Wi-Fi启动方法,它会立即成功.

// Get the HTML of a web page 'async'
public async Task<string> GetHtmlAsync(string url)
{
    using (var client = new HttpClient())
    using (var response = await client.GetAsync(url))
    {
        response.EnsureSuccessStatusCode();
        using (var content = response.Content)
        {
            return await content.ReadAsStringAsync();
        }
    }
}

// Wrapper for Polly to create an async retry policy
public async Task<TResult> RetryAsync<TResult, TException>(Task<TResult> task, int retries, int seconds) where TException : Exception
{
    return await Policy
               .Handle<TException>()
               .WaitAndRetryAsync(retries, wait => TimeSpan.FromSeconds(seconds))
               .ExecuteAsync(async () => await task);
}

// Call the method, it will retry 12 times with a gap of 5 seconds between tries
var html = await RetryAsync<string, HttpRequestException>(GetHtmlAsync("https://www.google.co.uk"), 12, 5);
Run Code Online (Sandbox Code Playgroud)

为什么即使我的连接已启用并在后续重试期间工作,该方法仍会继续失败?

Ric*_*lay 5

它随后失败了,因为你没有重新执行任何事情.Task表示异步执行的未来结果.订阅它只会给你结果,它不会重新运行代码.

把它想象成你已经开始的蛋计时器,你可以传递它,每个人都可以看到它是否已经完成但是如果它已经完成它们会立即看到它.在您的情况下,因为它第一次失败,它立即失败后续检查.

你想要的是重试调用:

public async Task<string> GetHtmlAsync(string url)
{
    using (var client = new HttpClient())
    using (var response = await client.GetAsync(url))
    {
        response.EnsureSuccessStatusCode();
        using (var content = response.Content)
        {
            return await content.ReadAsStringAsync();
        }
    }
}

// Wrapper for Polly to create an async retry policy
public async Task<TResult> RetryAsync<TResult, TException>(
    Func<Task<TResult>> taskInitiator, int retries, int seconds) where TException : Exception
{
    return await Policy
               .Handle<TException>()
               .WaitAndRetryAsync(retries, wait => TimeSpan.FromSeconds(seconds))
               .ExecuteAsync(async () => await taskInitiator());
}

// Call the method, it will retry 12 times with a gap of 5 seconds between tries
var html = await RetryAsync<string, HttpRequestException>(
    () => GetHtmlAsync("https://www.google.co.uk"), 12, 5);
Run Code Online (Sandbox Code Playgroud)