因此,我有一个用例,我想将列表传递给同时工作的异步函数。每个函数都会将其结果附加到传递的列表中。所以,我怀疑这会导致列表出现并发问题吗?
var errors = new List<Error>();
var awaitedTasks = new List<Task>();
awaitedTasks.Add(funcA(list));
awaitedTasks.Add(funcB(list));
awaitedTasks.Add(funcC(list));
awaitedTasks.Add(funcD(list));
await Task.WhenAll(awaitedTasks);
答案是,这取决于情况。有一些关于任务调度程序之类的细节,这些细节可能导致您的函数并行更改列表。
通常最好使用功能范例,您希望方法能够返回它们的值,而不是将它们附加到您提供的列表中。然后调用函数可以将它们收集到结果中。
var awaitedTasks = new List<Task>();
awaitedTasks.Add(funcA());
awaitedTasks.Add(funcB());
awaitedTasks.Add(funcC());
awaitedTasks.Add(funcD());
var list = await Task.WhenAll(awaitedTasks);
如果您需要在项目完成时而不是在所有项目完成后报告函数的进度,您可以使用适当的信号量向函数调用添加延续。
var reportingTasks = awaitedTasks.Select(async result => {
// code that updates `list` in a thread-safe way
// (or otherwise reports results)
}).ToList();
await Task.WhenAll(reportingTasks);
这样,管理复杂性的代码就全部集中在一个地方,而不是分散在各种异步函数中。