You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Task.WhenAll中的异步Web请求添加失败重试机制?

为异步Web请求添加可配置重试机制并兼容Task.WhenAll

你的核心问题是误用了async void导致无法继续使用Task.WhenAll——永远不要在非事件处理场景下用async void,它会脱离Task调度系统,无法被await也难以追踪异常。只需要保持方法返回Task,同时在内部加入重试逻辑即可。

基础解决方案

重构DoSomething方法,让它返回Task,并内置可配置的重试逻辑:

// 可通过参数指定重试次数,默认5次
async Task DoSomething(int retryCount = 5)
{
    for (int attempt = 0; attempt < retryCount; attempt++)
    {
        try
        {
            await client.PerformRequest();
            return; // 请求成功后直接返回,终止重试
        }
        catch (Exception ex)
        {
            Console.WriteLine($"请求失败,正在重试(第{attempt + 1}次):{ex.Message}");
            // 如果是最后一次重试仍失败,抛出异常让上层处理(可选)
            if (attempt == retryCount - 1)
                throw;
        }
    }
}

原来的批量调用代码几乎无需修改,只需在添加任务时按需传入重试次数:

var tasks = new List<Task>();
foreach (var component in doc.Descendants("component"))
{
    tasks.Add(DoSomething(5));            
}

await Task.WhenAll(tasks);

优化:添加重试间隔

为避免短时间内频繁请求加重不稳定服务的负担,可以在重试前加入延迟:

async Task DoSomething(int retryCount = 5, int retryDelayMs = 1000)
{
    for (int attempt = 0; attempt < retryCount; attempt++)
    {
        try
        {
            await client.PerformRequest();
            return;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"请求失败,正在重试(第{attempt + 1}次):{ex.Message}");
            if (attempt == retryCount - 1)
                throw;
            // 重试前等待指定时长
            await Task.Delay(retryDelayMs);
        }
    }
}

进阶:通用重试工具方法

如果多个地方都需要重试逻辑,可以封装成通用工具方法,提高复用性:

// 通用重试方法,接收异步操作、重试次数、重试间隔
async Task RetryAsync(Func<Task> asyncAction, int retryCount = 5, int retryDelayMs = 1000)
{
    for (int attempt = 0; attempt < retryCount; attempt++)
    {
        try
        {
            await asyncAction();
            return;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"操作失败,正在重试(第{attempt + 1}次):{ex.Message}");
            if (attempt == retryCount - 1)
                throw;
            await Task.Delay(retryDelayMs);
        }
    }
}

此时DoSomething可以简化为:

async Task DoSomething()
{
    // 复用通用重试逻辑,指定重试次数
    await RetryAsync(() => client.PerformRequest(), retryCount: 5);
}

这样你的批量调用代码可以完全保持原有结构,继续使用Task.WhenAll批量等待所有请求完成。

内容的提问来源于stack exchange,提问作者MakePeaceGreatAgain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 18:15:16