我有一些异步方法,我想尝试一定次数,直到它们返回 true 或达到最大尝试次数,中间有延迟。我已经能够得到我想要的结果,但无法减少冗余。
函数返回
Task<bool>
。
下面的代码是我试图概括的(因为只有函数调用行不同)
for (int attempts = 0; attempts < numOfTaskAttempts; ++attempts)
{
if (!await UpdateSingleUserStatistic(sendingPlayer, PlayfabServerKeys.DailyPuzzle, request.score))
await Task.Delay(taskAttemptDelay);
else
break
}
我尝试通过创建传递委托的方法(如下)来进行泛化,因为只有一行不同,但由于某种原因,看不到一种泛化它们的方法。
在搜索此站点时,我首先尝试传递任务而不是委托,但这只是运行了一次任务。
我编写了以下方法,其中 Func 的签名随着提供的字符串参数的变化而变化。我似乎找不到一种方法使它们更通用(即只有一个方法并传递任务和/或委托)。
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;
}
他们如何被称为:
bool isSuccess = false;
if (await CallAsyncMethodWithRetries(CreateAndSetTopPuzzlePlayers))
if (await CallAsyncMethodWithRetries(SetTitleData, PlayfabServerKeys.DailyPuzzle, dailyPuzzle))
isSuccess = await CallAsyncMethodWithRetries(ResetLeaderboard, PlayfabServerKeys.DailyPuzzle);
任何减少冗余代码的方法将不胜感激。我对异步编程还很陌生,所以解决方案可能就在我面前,但我可能不知道。
有多种方法可以解决这个问题,包括,正如问题评论中提到的,具有可变数量参数的委托,以及使用反射。
但是在这些情况下,最干净且实际上更功能性的方法是简单地让你的
CallAsyncMethodWithRetries
将Func<Task<bool>>
作为参数,然后使用关闭的lambda表达式来调用它(如closure中)使用所需参数的实际方法调用,例如:
await CallAsyncMethodWithRetries(() => ResetLeaderboard(PlayfabServerKeys.DailyPuzzle));
这是一个完整的示例(稍微简化了您的代码,我删除了参数默认值):https://dotnetfiddle.net/JVKUYP