Using Async/Await inside nested LINQ-Select without having to use Task.WhenAll
我试图在另一个选择语句内的一个选择语句内等待异步操作。
1 2 3 4 5 6 7 8 9
| var result = someList
.Select(table => new Table
{
Columns = table .Select(async column => new Column
{
Constraints = await GetColumnConstraints ()
})
})
.ToList(); |
这里的"问题"是嵌套的select语句返回任务列表。 通常,我们将使用Task.WhenAll()等待所有任务。 因此,最简单的方法是将Columns的类型从List更改为List>,然后使用SelectMany()来获取每个Task并等待它们。 但是我不能更改列的数据类型。
我怎样才能做到这一点? 我找不到不涉及Task.WhenAll()的任何解决方案
-
我看不到为什么您需要更改Columns的数据类型以使用Task.WhenAll。 介意解释吗? 因为结果仍然是Column
-
那stackoverflow.com/questions/35011656/async-await-in-linq-sel怎么样?
-
Constraints = await Task.WhenAll(GetColumnConstraints())有什么问题?
您不需要更改Column的类型,只需要在表的初始化程序之外对await的结果进行更改。这样,您就可以在columnTasks和await中收集所有结果,然后创建新表。
1 2 3 4 5 6 7 8 9 10 11 12
| var result = someList .Select(async table =>
{
var columnTasks = table .Select(async column => new Column ()
{
Constraints = await GetColumnConstraints ()
});
var columns = await Task .WhenAll(columnTasks );
return new Table ()
{
Columns = columns
};
}); |
请注意,尽管async沿链条向上移动,所以reuslt现在是IEnumerable>,您必须await Task.WhenAll才能获得Table的最终集合
1
| var tables = await Task.WhenAll(result); |
显然,Somelist是Tables的序列,其中每个Table都具有Columns的序列。
在我看来,这些表的列不影响GetColumnConstraints()。为什么每列调用一次此函数?如果只调用一次它会不会更有效率?
1 2 3 4 5 6 7 8 9 10
| var columnConstraints = await GetColumnConstraintsAsync ();
var result = tables .Select(table => new Table
{
Columns = table .Select(column => new Column
{
Constraints = columnConstraints,
...
})
})
.ToList(); |
可能是因为您简化了问题,而被枚举的表和列确实会影响所获取的约束,例如,因为它们被用作输入变量。也许,如果您第二次调用该函数,则会得到不同的约束?
如果确实需要获取每个表的每个列的约束,则在创建表之前首先等待获取约束:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var result = tables .Select(table =>
{
var columnTasks = table .Select(column => GetColumnContraintsAsync (...)).ToArray();
// all tasks are running now, wait until all are completed:
await Task .WhenAll(columnTasks );
// fetch the result from every task:
var columnTaskResults = columnTasks .Select(columnTask => columnTask .Result).ToList();
// create a Table with these results and return it:
return new Table
{
Columns = columnTaskResults,
};
})
.ToList(); |
-
我认为不需要columnTasks.Select,因为await Task.WhenAll(columnTasks)已经返回了Column的集合
-
如果结果共享相同的类型,则Task.WhenAll将返回结果的集合。 文档和签名public static System.Threading.Tasks.Task WhenAll (System.Collections.Generic.IEnumerable> tasks);
-
根据您的链接,Task.WhenAll的返回值是:"一个代表所有提供的任务完成的任务。" 这些示例还显示,当此任务运行完成时,将提取所有原始任务的结果以访问函数的返回值