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); // 此处的后续处理可确保所有字典添加操作已完成
为什么这样能解决问题
- 完整覆盖所有场景:不管
GetAsync成功还是失败,ProcessSearchResult中的逻辑都会执行(失败时进入catch块),不会出现逻辑被跳过的情况。 - 明确的任务等待:
Task.WhenAll等待的是包含完整逻辑的任务,确保所有条目从缓存获取到字典添加的流程全部完成后,才会执行后续代码。 - 更清晰的异常处理:可以针对每个条目单独处理异常,避免单个条目失败影响其他条目的执行。
内容的提问来源于stack exchange,提问作者Geetha
相关产品推荐
相关产品推荐

