c# - 为什么 HttpClient 在随后使用 Polly 重试期间继续失败?

标签 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);

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

最佳答案

它随后失败了,因为你没有重新执行任何东西。 Task 表示异步执行的 future 结果。订阅它只会给你结果,它不会重新运行代码。

把它想象成一个您已经启动的煮蛋计时器,您可以将它传递给所有人,每个人都可以看到它是否已经结束,但如果已经结束,他们会立即看到。在您的情况下,由于它第一次失败,它立即无法通过后续检查。

你想要的是重试调用:

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

关于c# - 为什么 HttpClient 在随后使用 Polly 重试期间继续失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46788709/

相关文章:

.net-4.0 - 使用Parallel for循环时索引超出范围异常

azure - 使用 QueueBackgroundWorkItem 进行事件中心发送数据操作是个好主意吗?

c# - 为什么要使用 ICollection<T> 而不是 List<T>,如果我使用 ICollection<T>,那么如何使用 AddRange、Insert 和其他列表方法

c# - 在 C# Telegram Bots 中使用键盘编辑短信

javascript - 如何使用 Deferred 顺序运行代码?

c++ - 调用 QSound 调用,它们之间有延迟 Qt C++

c# - 任务调度程序: when awaiting in a Task. Factory.StartNew,线程是否返回池中?

c# - 将 Char 列表转换为 int 列表 C#

c# - HtmlAgilityPack 在 C# 中同时获取两个节点

node.js - 使用两个不同异步函数的结果