如何正确等待元组形式的任务列表并关联对应参数?
并行执行任务并关联结果与参数的实现方案
你可以通过Task.WhenAll实现任务并行执行,同时利用任务列表与结果数组的顺序一致性,将每个任务的结果和对应的offset关联起来。以下是两种简洁的实现方式:
方式一:保留任务与offset的关联,等待后匹配结果
先创建包含任务和offset的列表,并行等待所有任务完成后,通过顺序匹配将结果与offset组合:
List<(Task<MyResult> Task, int Offset)> taskWithOffsets = new(); if (myParam != 0) { for(int i = 0; i < myParam; i++) { // 调用LoadData会立即启动任务,天然实现并行 taskWithOffsets.Add((service.LoadData(myParam + i, cancellationToken), i)); } } // 并行等待所有任务完成,结果数组顺序与taskWithOffsets中的任务顺序完全一致 MyResult[] results = await Task.WhenAll(taskWithOffsets.Select(t => t.Task)); // 构建最终的结果-offset列表 List<(MyResult Result, int Offset)> finalList = new(); for (int j = 0; j < taskWithOffsets.Count; j++) { finalList.Add((results[j], taskWithOffsets[j].Offset)); }
方式二:让任务直接返回包含结果和offset的元组
在创建任务时,就定义任务执行完成后返回(MyResult, int)元组,Task.WhenAll完成后直接得到目标列表:
List<Task<(MyResult Result, int Offset)>> tasks = new(); if (myParam != 0) { for(int i = 0; i < myParam; i++) { // 捕获当前循环的i值,避免闭包引用同一个变量的陷阱 int currentOffset = i; tasks.Add(Task.Run(async () => { MyResult result = await service.LoadData(myParam + currentOffset, cancellationToken); return (result, currentOffset); }, cancellationToken)); } } // 并行等待所有任务,直接得到最终结果列表 List<(MyResult Result, int Offset)> finalList = (await Task.WhenAll(tasks)).ToList();
关键注意事项
- 两种方式都能实现并行:方式一中调用
LoadData返回Task时任务已启动,方式二中Task.Run会立即调度任务执行。 - 方式二中必须通过
currentOffset捕获循环变量,否则所有任务会引用同一个i变量,导致最终offset值全部为循环结束后的myParam。
内容的提问来源于stack exchange,提问作者Yuropoor
相关产品推荐
相关产品推荐

