I have some async methods I want to try a set number of times until they return true or the max attempts have been reached, with a delay in between. I've been able to get the outcome I desire, but have not been able to reduce the redundancy.
The functions return Task<bool>.
The below code is what I'm trying to generalize (as only the function call line is different)
for (int attempts = 0; attempts < numOfTaskAttempts; ++attempts) { if (!await UpdateSingleUserStatistic(sendingPlayer, PlayfabServerKeys.DailyPuzzle, request.score)) await Task.Delay(taskAttemptDelay); else break } I tried to generalize by creating methods passing delegates (below) since the only one line differs, but for some reason, can't see a way to generalize them.
On searching this site, I first tried passing a Task instead of a delegate, but that just ran the task once.
I wrote the below methods where the signature of the Func changes as do the string arguments provided. I can't seem to find a way to make them more generic (i.e. have just one method and pass a task and/or a delegate).
private static async Task<bool> CallAsyncMethodWithRetries( Func<Task<bool>> callback, int maxAttempts = numOfTaskAttempts, int delay = taskAttemptDelay) { int numOfTries = 0; while (!await callback() && ++numOfTries < maxAttempts) await Task.Delay(delay); return numOfTries < maxAttempts; } private static async Task<bool> CallAsyncMethodWithRetries( Func<string, Task<bool>> callback, string arg, int maxAttempts = numOfTaskAttempts, int delay = taskAttemptDelay) { int numOfTries = 0; while (!await callback(arg) && ++numOfTries < maxAttempts) await Task.Delay(delay); return numOfTries < maxAttempts; } private static async Task<bool> CallAsyncMethodWithRetries( Func<string, string, Task<bool>> callback, string arg1, string arg2, int maxAttempts = numOfTaskAttempts, int delay = taskAttemptDelay) { int numOfTries = 0; while (!await callback(arg1, arg2) && ++numOfTries < maxAttempts) await Task.Delay(delay); return numOfTries < maxAttempts; } How they are called:
bool isSuccess = false; if (await CallAsyncMethodWithRetries(CreateAndSetTopPuzzlePlayers)) if (await CallAsyncMethodWithRetries(SetTitleData, PlayfabServerKeys.DailyPuzzle, dailyPuzzle)) isSuccess = await CallAsyncMethodWithRetries(ResetLeaderboard, PlayfabServerKeys.DailyPuzzle); Any way to reduce the redundant code would be appreciated. I'm still fairly new at async programming, so the solution could be right in front of me and I probably wouldn't know it.