Home > OS >  Async generic retry
Async generic retry

Time:12-16

I have this

public static async Task Retry<T>(Func<T> action, TimeSpan retryInterval, int maxAttemptCount = 3)
{
    var exceptions = new List<Exception>();

    for (int attempted = 0; attempted < maxAttemptCount; attempted  )
    {
        try
        {
            if (attempted > 0)
            {
                Thread.Sleep(retryInterval);
            }
            return await action();
        }
        catch (Exception ex)
        {
            exceptions.Add(ex);
        }
    }
    throw new AggregateException(exceptions);
}

and try to run this by

await Retry(() => SaveFile(command, tracker.ActivityId, blobService), TimeSpan.FromSeconds(5), retryCount);

but i got error in Retry in return await action() (T does not contain definition for getAwaiter)

i need to return from the loop when action is done

and my action

Task SaveFile<TCommand>(TCommand command, string activityId, IBlobService blobService) where TCommand : DomainComman

CodePudding user response:

There are a few issues here.

  1. action returns T, you cannot await this, you can only await Task or Task<T>. So if you want to await action it should have the signature Func<Task<T>>
  2. Your return type is wrong. It looks like you want to return a T, then the return type should be Task<T>
  3. If you are using asynchronous code you should not be using Thread.Sleep, use Task.Delay instead, and await this.

You might also want to add some logging, or a custom exception to make it clearer that this was a repeated failure. Someone looking at a aggregate exception with three duplicates might not immediately figure out what is going on.

CodePudding user response:

Async functions returns Task for beeing awaitable. So in your code you TResult is T and you need to redifine the Func<T> to Func<Task<T>>.

As you return the result of action you need also to change the return type of your function to Task<T>

So you end up with:

public static async Task Retry<T>(Func<T> action, TimeSpan retryInterval, int maxAttemptCount = 3)

as SaveFile seams also to be async so you should change the call to:

await Retry(async () => await SaveFile(command, tracker.ActivityId, blobService), TimeSpan.FromSeconds(5), retryCount);
  • Related