1

I have a couple of web-requests that I want to perform and that are independent. So I put all these tasks into a loop and use WhenAll to just await when all tasks finished.

var tasks = new List<Task>();
foreach (var component in doc.Descendants("component"))
{
    tasks.Add(DoSomething());            
}

await Task.WhenAll(tasks);

where DoSomething is this:

async Task DoSomething() => await client.PerformRequest();

Now I have a problem as the service is quite unstable and many of these requests fail. So I just want to re-send them for a configurable amount, say five times. So when one request fails, just retry it. How can I do that?

I've tried this, however that doesn't return a Task anymore and therefor there's no way to use Task.WhenAll.

async void DoSomething()
{
    for (int i = 0; i < 5; i++)
    {
        try
        {
            await client1.PerformRequest();
            break;
        }
        catch
        {
            Console.WriteLine("retrying");
        }
    }
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
  • 2
    This can be handled by Polly retry policies at the HttpClient level and can be easily configured with `AddHttpClient`. Check [Implement HTTP call retries with exponential backoff with IHttpClientFactory and Polly policies](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/implement-http-call-retries-exponential-backoff-polly) – Panagiotis Kanavos Jul 21 '23 at 09:34
  • 1
    You can also look into using a tool that handles all these retries for you. Polly is excellent, and free, and I highly recommend it https://github.com/App-vNext/Polly – DavidG Jul 21 '23 at 09:36
  • You can use Polly by itself to retry any operation but HttpClient integration make retries almost transparent and can handle problems like server throttling (429) by inspecting failure responses directly – Panagiotis Kanavos Jul 21 '23 at 09:36
  • 1
    sh**... I forgot t mention that this is no HTTP- but a SOAP-request :| – MakePeaceGreatAgain Jul 21 '23 at 09:38
  • Related: [How to use Task.WhenAny and implement retry](https://stackoverflow.com/questions/43763982/how-to-use-task-whenany-and-implement-retry). – Theodor Zoulias Jul 21 '23 at 09:52

1 Answers1

2

You can use Polly.

In the example polly is retrying 3 times before throwing the exception finally. In the documentation link above you can find several examples to retry, circuit break, etc.

   await Policy
        .Handle<Exception>()
        .RetryAsync(3, onRetry: (exception, retryCount, context) =>
        {
            // Do your logging or setup for retries here
            Console.WriteLine($"Retry Count: {retryCount}");
        }).ExecuteAsync(async () => {
            
            // Call your SOAP service here
            await CallSoapService();
        });

Working example dotnetfiddle

Martin
  • 3,096
  • 1
  • 26
  • 46