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

C#中使用ContinueWith无法确保后续任务完成的问题

解决方案:用Async/Await替代ContinueWith确保操作完成

你的问题出在ContinueWith搭配TaskContinuationOptions.OnlyOnRanToCompletion的使用方式上——当缓存获取操作GetAsync失败时,后续的字典添加逻辑会直接跳过,且Task.WhenAll不会等待这些未触发的任务,导致你无法确保所有添加操作都执行完成。此外,ContinueWith的异常处理逻辑不够直观,容易遗漏异常场景。

修改后的代码

拆分逻辑,将单个条目的缓存获取和字典添加封装为独立异步方法,再通过async/await统一等待所有任务完成:

private async Task PopulateValuesFromCacheToDictionary(List<Search> searchResults)
{
    var tasks = new List<Task>();
    foreach (var result in searchResults)
    {
        var currentId = result.Id;
        tasks.Add(ProcessSearchResult(currentId));
    }
    await Task.WhenAll(tasks);
}

private async Task ProcessSearchResult(int currentId)
{
    try
    {
        var cacheValue = await _appCache.GetAsync(currentId);
        
        if (_appDictionary.TryAdd(currentId, cacheValue))
        {
            _logger.LogInformation($"Successfully added entry for {currentId} in dictionary");
        }
        else
        {
            _logger.LogError($"Unable to add entry {currentId} in dictionary");
        }
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, $"Failed to fetch cache value for {currentId}");
        // 根据业务需求处理异常,比如记录后忽略或执行降级逻辑
    }
}

调用方式

await PopulateValuesFromCacheToDictionary(searchResults);

// 此处的后续处理可确保所有字典添加操作已完成

为什么这样能解决问题

  1. 完整覆盖所有场景:不管GetAsync成功还是失败,ProcessSearchResult中的逻辑都会执行(失败时进入catch块),不会出现逻辑被跳过的情况。
  2. 明确的任务等待:Task.WhenAll等待的是包含完整逻辑的任务,确保所有条目从缓存获取到字典添加的流程全部完成后,才会执行后续代码。
  3. 更清晰的异常处理:可以针对每个条目单独处理异常,避免单个条目失败影响其他条目的执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 17:20:16