如何访问异步方法被调用时处于可用状态的相关上下文变量?
要实现故障时获取对应动物的国家信息,核心是把每个API调用任务和对应的动物上下文绑定,避免任务和触发它的动物信息脱节,共有两种常用实现方式:
方式1:绑定任务与动物上下文,捕获全局异常后匹配故障任务
这种方式改动最小,仅需调整存储结构,将任务和对应的动物信息绑定存储,异常触发后直接匹配故障任务对应的动物即可:
// 将任务与对应动物绑定存储,不再仅保存Task<string> var animalQueryTasks = new List<(Animal TargetAnimal, Task<string> GetNameTask)>(); foreach (var animal in animals) { animalQueryTasks.Add((animal, this.zooApi.GetNameAsync(animal))); } try { await Task.WhenAll(animalQueryTasks.Select(x => x.GetNameTask)); } catch (Exception e) { // 匹配第一个故障的任务,取出关联的动物信息 var faultedTask = animalQueryTasks.First(x => x.GetNameTask.IsFaulted); var innerException = faultedTask.GetNameTask.Exception.InnerExceptions.First(); this.logger.LogError(innerException, "来自{Country}的动物名称查询失败", faultedTask.TargetAnimal.Country); }
方式2:单任务独立捕获异常,支持批量处理多故障场景
如果需要同时记录所有失败请求的日志(而非仅第一个故障),可以给每个API调用套一层异常捕获,直接把上下文和异常一起返回:
// 定义查询结果结构,绑定动物、返回结果、异常信息 public class AnimalNameResult { public Animal Animal { get; set; } public string Name { get; set; } public Exception Error { get; set; } public bool IsSuccess => Error == null; } // 批量发起请求,每个请求独立处理异常 var queryTasks = animals.Select(async animal => { try { var name = await this.zooApi.GetNameAsync(animal); return new AnimalNameResult { Animal = animal, Name = name }; } catch (Exception ex) { return new AnimalNameResult { Animal = animal, Error = ex }; } }); // 等待所有请求完成,不会触发全局异常 var allResults = await Task.WhenAll(queryTasks); // 遍历处理所有失败请求 foreach (var failedResult in allResults.Where(x => !x.IsSuccess)) { this.logger.LogError(failedResult.Error, "来自{Country}的动物名称查询失败", failedResult.Animal.Country); }
原代码问题说明
你之前的代码无法实现需求的核心原因是:catch块位于循环之外,直接使用的animal变量是循环迭代的最终值,和触发故障的任务没有绑定关系,无法拿到对应出错动物的信息。
内容的提问来源于stack exchange,提问作者user33276346
相关产品推荐
相关产品推荐

