Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么HttpClient在使用Polly的后续重试中继续失败?_C#_Asynchronous_Task Parallel Library_Polly - Fatal编程技术网

C# 为什么HttpClient在使用Polly的后续重试中继续失败?

C# 为什么HttpClient在使用Polly的后续重试中继续失败?,c#,asynchronous,task-parallel-library,polly,C#,Asynchronous,Task Parallel Library,Polly,我有几种方法需要某种internet连接。如果连接失败,我希望在失败之前重试该方法一段时间。由于应用程序可以在等待成功响应的同时愉快地继续运行,因此我希望异步执行此操作 我使用来实现异步重试逻辑,利用任务 我通过在禁用Wi-Fi的情况下启动进程并在重试窗口期间启用它来模拟断开连接。我希望在再次启用连接后,该方法在重试时会成功,我看到的是,该方法会继续抛出一个HttpRequestException,就好像连接断开一样,直到重试完成,并在该点抛出给调用方。 如果我在正常情况下启用Wi-Fi的情况下

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

我使用来实现异步重试逻辑,利用
任务

我通过在禁用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);
//获取网页“async”的HTML
公共异步任务GetHtmlAsync(字符串url)
{
使用(var client=new HttpClient())
使用(var response=await client.GetAsync(url))
{
response.EnsureSuccessStatusCode();
使用(var content=response.content)
{
返回wait content.ReadAsStringAsync();
}
}
}
//Polly创建异步重试策略的包装器
public async Task RetryAsync(Task Task,int retries,int seconds),其中TException:Exception
{
退货等待政策
.Handle()
.WaitAndRetryAsync(重试,等待=>TimeSpan.FromSeconds(秒))
.ExecuteAsync(异步()=>等待任务);
}
//调用该方法,它将重试12次,每次尝试之间的间隔为5秒
var html=await RetryAsync(GetHtmlAsync(“https://www.google.co.uk"), 12, 5);

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

它随后会失败,因为您没有重新执行任何操作<代码>任务表示异步执行的未来结果。订阅它只会给出结果,而不会重新运行代码

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

您需要的是重试调用:

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);
公共异步任务GetHtmlAsync(字符串url) { 使用(var client=new HttpClient()) 使用(var response=await client.GetAsync(url)) { response.EnsureSuccessStatusCode(); 使用(var content=response.content) { 返回wait content.ReadAsStringAsync(); } } } //Polly创建异步重试策略的包装器 公共异步任务RetryAsync( Func taskInitiator,int重试,int秒),其中TException:Exception { 退货等待政策 .Handle() .WaitAndRetryAsync(重试,等待=>TimeSpan.FromSeconds(秒)) .ExecuteAsync(异步()=>await taskInitiator()); } //调用该方法,它将重试12次,每次尝试之间的间隔为5秒 var html=await RetryAsync( ()=>GetHtmlAsync(“https://www.google.co.uk"), 12, 5);
您不应该创建这么多HttpClient实例。从长远来看,这将造成问题。创建一个实例并重新使用它。@NKosi您是基于我在这里展示的5秒重试,还是重新创建
HttpClient
通常会很昂贵?我应该指出,这次重试时间很短,只是为了排除故障。实际上,我可能会在两次尝试之间等待至少30秒。这更多地是关于为每个尝试创建的底层TCP连接client@Nkosi太棒了,谢谢。我不知道。我会去读的。太棒了,这很有道理。我很恼火,这太明显了,我想我已经变成了代码盲。最终在这个几乎相同的问题上发现了相同的问题:。但是通过在q,equalsk的第一个版本中发布您的完整代码,您马上就得到了正确的答案@理查德萨莱:带蛋计时器的伟大的梅特弗尔!