2017-10-17 8 views
4

私はいくつかの種類のインターネット接続を必要とするいくつかの方法があります。接続が失敗した場合、失敗する前に一定期間メソッドを再試行したい。応答がうまくいくのを待っている間、アプリケーションをうまく実行し続けることができるので、私はこれを非同期的に行いたいと思っています。なぜPollyを使用して後続の再試行中にHttpClientが失敗し続けるのですか?

Tasksを活用して非同期リトライロジックを実装するには、Polly (5.3.1)を使用しています。

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

なぜこの方法は、私の接続が有効になっており、その後の再試行の間に働いているにもかかわらず、失敗し続けるのでしょうか?

+0

あなたはHttpClientをのように多くのインスタンスを作成しないでください。長期的には問題が発生します。 1つのインスタンスを作成して再利用します。 – Nkosi

+0

@ NKosiここで示した5秒間の再試行でそれをベースにしているのですか?それとも、一般的に 'HttpClient'を再作成するのにかかる費用はかかりますか?私は、この再試行はトラブルシューティングのためだけに短いことを指摘しなければなりません。実際には試行の間に少なくとも30秒待つでしょう。 – Equalsk

+0

https://stackoverflow.com/questions/24043679/how-many-httpclients-should-i-create – Nkosi

答えて

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

素晴らしいです、それは完璧な意味合いです。私はそれがとても分かりません、私はコードブラインドになったと思う迷惑だ。 – Equalsk

+0

+1。最終的にこのほぼ同一の質問で明らかになった同じ問題:https://stackoverflow.com/questions/46414976/c-sharp-polly-async-await-wait-for-user-confirmation-before-retry/46421518#46421518しかし、qの最初のバージョンであるequalskに完全なコードを投稿することで、すぐに正しい答えが得られます。 @richardszalay:卵のタイマーと偉大な流星! –

関連する問題