如何在C#中泛化带有委托参数的异步方法以减少冗余代码?

问题描述 投票:0回答:1

我有一些异步方法,我想尝试一定次数,直到它们返回 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);

任何减少冗余代码的方法将不胜感激。我对异步编程还很陌生,所以解决方案可能就在我面前,但我可能不知道。

c# asynchronous generics task
1个回答
0
投票

有多种方法可以解决这个问题,包括,正如问题评论中提到的,具有可变数量参数的委托,以及使用反射。

但是在这些情况下,最干净且实际上更功能性的方法是简单地让你的

CallAsyncMethodWithRetries
Func<Task<bool>>
作为参数,然后使用关闭的lambda表达式来调用它(如closure中)使用所需参数的实际方法调用,例如:

await CallAsyncMethodWithRetries(() => ResetLeaderboard(PlayfabServerKeys.DailyPuzzle));

这是一个完整的示例(稍微简化了您的代码,我删除了参数默认值):https://dotnetfiddle.net/JVKUYP

© www.soinside.com 2019 - 2024. All rights reserved.