为什么 HttpClient 在随后使用 Polly 重试期间继续失败?
Why does HttpClient continue to fail during subsequent retries using Polly?
我有几种方法需要某种互联网连接。如果连接失败,我想在失败之前重试该方法一段时间。由于应用程序可以在等待成功响应的同时愉快地继续 运行 我想异步执行此操作。
我正在使用 Polly (5.3.1) 来实现利用 Tasks
的异步重试逻辑。
我通过在禁用 Wi-Fi 的情况下启动进程并在重试期间启用它来模拟断开连接 window。我期待在再次启用我的连接后,该方法在重试时会成功,我所看到的是该方法继续抛出 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
表示异步执行的未来结果。订阅它只会给你结果,它不会重新运行代码。
把它想象成一个你已经启动的煮蛋计时器,你可以把它传递给每个人,每个人都可以看到它是否已经结束,但如果已经结束,他们会立即看到。在你的例子中,由于它第一次失败,它立即无法通过后续检查。
您想要重试调用:
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);
我有几种方法需要某种互联网连接。如果连接失败,我想在失败之前重试该方法一段时间。由于应用程序可以在等待成功响应的同时愉快地继续 运行 我想异步执行此操作。
我正在使用 Polly (5.3.1) 来实现利用 Tasks
的异步重试逻辑。
我通过在禁用 Wi-Fi 的情况下启动进程并在重试期间启用它来模拟断开连接 window。我期待在再次启用我的连接后,该方法在重试时会成功,我所看到的是该方法继续抛出 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
表示异步执行的未来结果。订阅它只会给你结果,它不会重新运行代码。
把它想象成一个你已经启动的煮蛋计时器,你可以把它传递给每个人,每个人都可以看到它是否已经结束,但如果已经结束,他们会立即看到。在你的例子中,由于它第一次失败,它立即无法通过后续检查。
您想要重试调用:
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);