提问人:Samhain323 提问时间:11/17/2023 最后编辑:Theodor ZouliasSamhain323 更新时间:11/17/2023 访问量:89
如何在C#中使用委托参数泛化异步方法以减少冗余代码?
How to generalize async methods with delegate parameters in C# to reduce redundant code?
问:
我有一些异步方法,我想尝试一定次数,直到它们返回 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);
任何减少冗余代码的方法都将不胜感激。我对异步编程还很陌生,所以解决方案可能就在我面前,我可能不知道。
答:
3赞
Julio Di Egidio
11/17/2023
#1
有多种方法可以解决这个问题,包括,正如在对问题的评论中提到的,具有可变数量参数的代表,以及使用反射。
但是,在这些情况下,最干净且实际上更实用的方法是简单地将 as 参数作为参数,然后使用 lambda 表达式调用它,该表达式使用所需的参数关闭(作为闭包)实际方法调用,例如:CallAsyncMethodWithRetries
Func<Task<bool>>
await CallAsyncMethodWithRetries(() => ResetLeaderboard(PlayfabServerKeys.DailyPuzzle));
这是一个完整的示例(稍微简化了您的代码,我删除了参数默认值): https://dotnetfiddle.net/JVKUYP
评论
0赞
Enigmativity
11/17/2023
需要明确的是,您是在建议 OP 的第一种方法是答案。
0赞
Julio Di Egidio
11/17/2023
虽然我的答案只是部分与 OP 的第一个片段相匹配,但这只是偶然的,OP 中没有答案,而是在考虑超载的签名:事实上,我给出了一个甚至没有受到关注的答案,事实上我已经解释了这个想法是什么以及它是如何工作的。
0赞
Enigmativity
11/17/2023
你说的“甚至在雷达下”是什么意思?你的意思是“甚至不在雷达上”吗?
评论